如何将迭代器限制为前向迭代器?

Meh*_*dad 6 c++ templates iterator

我有一个需要多次枚举迭代器的函数,但根据MSDN,"一旦你增加了输入迭代器的任何副本,其他副本都不能安全地进行比较,解除引用或增加."

因此,为了使事情变得更容易,我不想为复制数据和枚举副本的非正向迭代器创建单独的实现,而是希望将我的方法限制为只接收前向迭代器,并静态拒绝输入迭代器.

现在我有类似的东西:

template<typename It, typename TCallback /*signature: bool(value_type)*/>
bool EnumerateTwice(const It &begin, const It &end, TCallback callback)
{
    for (It it = begin; it != end; ++it)
        if (!callback(*it))
            return false;
    for (It it = begin; it != end; ++it)
        if (!callback(*it))
            return false;
    return true;
}
Run Code Online (Sandbox Code Playgroud)

但没有什么限制It成为一个前向迭代器.

如何将限制放在模板化函数上?(C++ 03)

Ker*_* SB 5

您可以使用SFINAE并替换bool为:

typename enable_if<
   is_same<typename std::iterator_traits<It>::iterator_category,
           std::forward_iterator_tag>::value,
   bool>::type
Run Code Online (Sandbox Code Playgroud)

如果您不想从Boost或TR1中提取它们,您可能需要定义is_sameenable_if自己:

template <typename A, typename B>
struct is_same { static const bool value = false; };

template <typename T>
struct is_same<T, T> { static const bool value = true; };

template <bool, typename> struct enable_if { };
template <typename T> struct enable_if<true, T> { typedef T type; };
Run Code Online (Sandbox Code Playgroud)

  • 这将拒绝双向和随机访问迭代器.使用`is_base_of`而不是`is_same`来获得正确的语义. (9认同)
  • @Kerrek:OP表示他想静态拒绝输入迭代器,而不是将迭代器限制为只转发迭代器(这很愚蠢).标准迭代器标签已经使用了继承这个确切的原因 - "forward_iterator_tag"继承自`input_iterator_tag`,`bidirectional_iterator_tag`继承自`forward_iterator_tag`,`random_access_iterator_tag`继承自`bidirectional_iterator_tag`. (2认同)