我能否获取模板类型的"iterator",无论该类型是数组还是类似 STL 的容器?

Can I get the "iterator" for a template type, regardless if that type is an array or STL-like container?

本文关键字:类型 数组 STL 获取 iterator      更新时间:2023-10-16

下面是我的例子:

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本身,但在现实世界中,这会很麻烦,因为类很大。

使用decltypestd::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。范围:

#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;

这只是一个单独的专业化,那会有多糟糕?

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::endauto:

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