【C++】コンテナを渡したらイテレータを返し、配列を渡したらポインタを返す

C++,小ネタ

std:begin()std::end()の戻り値を受ける変数を宣言するために使います。大抵はautoで対応できるものですが、autoが使えないケースで使いたかったので作ってみました。SFINAEとか考える必要もなく、意外と簡単に実装できます。

実装と使用例

実装

#include <iterator>
#include <utility>

template <typename T>
struct GetIteratorImpl
{
    using iterator = decltype(std::begin(std::declval<T &>()));
    using reference = typename std::iterator_traits<iterator>::reference;
    using value_type = typename std::iterator_traits<iterator>::value_type;
    using pointer = typename std::iterator_traits<iterator>::pointer;
};

template <typename T>
using GetIterator = typename GetIteratorImpl<T>::iterator;

template <typename T>
using GetReference = typename GetIteratorImpl<T>::reference;

template <typename T>
using GetValueType = typename GetIteratorImpl<T>::value_type;

template <typename T>
using GetPointer = typename _GetIteratorImpl<T>::pointer;

std::begin()std::end()の戻り値を受けたいので、decltype()std::begin()の戻り値を指定します。ただ、これだけだとオーバーロードの解決ができません。std::declval<>()std::begin()の引数に指定することで、テンプレート引数Tを明示し、オーバーロードを解決します。また、std::begin()の引数は左辺値参照なので、std::declval<T &>()&を付けておく必要があります。

おまけで、std::iterator_traits<>を使って、要素の型や、要素への参照型、要素へのポインタも取得できるようにしてみました。

使用例

使い道は少ないですが、autoが使えない状況、たとえばテンプレートを使ったクラスのメンバ変数の型としてイテレータやポインタが必要な場合に使えます。

template <typename T>
class SampleClass
{
        :
    GetIterator<T> iter_;
        :
};

C++,小ネタ

Posted by izadori