Могу ли я получить «итератор» для типа шаблона, независимо от того, является ли этот тип массивом или контейнером, подобным STL? - PullRequest
2 голосов
/ 23 февраля 2012

Вот мой пример:

template<typename TContainer>
class MyClass
{
public:
   typedef typename SomeUnknownHelper<TContainer>::iterator iterator;
};

std::vector<int>::iterator i = MyClass<std::vector<int>>::iterator;
int *pi = MyClass<int[20]>::iterator;

В принципе, я не знаю, как писать SomeUnknownHelper.

Я знаю, что мог бы специализироваться MyClass сам, но в моем случае с реальным миром это будет хлопотно, потому что класс большой.

Ответы [ 2 ]

2 голосов
/ 23 февраля 2012

Это легко сделать с помощью decltype и std::begin:

#include <iterator>
#include <utility>

namespace tricks{
  using std::begin; // fallback for ADL
  template<class C>
  auto adl_begin(C& c) -> decltype(begin(c)); // undefined, not needed
  template<class C>
  auto adl_begin(C const& c) -> decltype(begin(c)); // undefined, not needed
}

template<typename TContainer>
class MyClass
{
public:
   typedef decltype(tricks::adl_begin(std::declval<TContainer>())) iterator;
};

std::vector<int>::iterator i = MyClass<std::vector<int>>::iterator;
int *pi = MyClass<int[20]>::iterator;

Еще лучшим вариантом может быть использование Boost.Range:

#include <boost/range/metafunctions.hpp>

template<typename TContainer>
class MyClass
{
public:
   typedef typename boost::range_iterator<TContainer>::type iterator;
};

std::vector<int>::iterator i = MyClass<std::vector<int>>::iterator;
int *pi = MyClass<int[20]>::iterator;
1 голос
/ 23 февраля 2012

Это только одна специализация, насколько это может быть плохо?

template <typename T> struct ContainerTrait
{
    typedef typename T::iterator iterator;
    typedef typename T::const_iterator const_iterator;
};

template <typename T, unsigned int N> struct ContainerTrait<T[N]>
{
    typedef T * iterator;
    typedef T const * const_iterator;
};

Кроме того, вы можете использовать бесплатные std::begin / std::end и auto:

auto it = std::begin(x);  // x could be vector<int> or float[10]...
...