MSVC ++ 17 std :: copy期望“ operator-”用于自定义迭代器

Dew*_*wfy 3 c++ stl c++14

我将项目从VC ++ 2015迁移到VC ++2017。我有自己的迭代器实现。它设置了只进操作:

template <class Container>
struct NodeTableIterator
{
    typedef NodeTableIterator<Container> this_t;
    this_t& operator ++();
    this_t operator ++(int);
};
Run Code Online (Sandbox Code Playgroud)

我在代码中的某个地方使用它 std::copy

std::copy(tbl.begin(), tbl.end(),
        std::ostream_iterator<int>(std::cout, ", "));    
Run Code Online (Sandbox Code Playgroud)

这条线在VC ++ 2015中完美工作,但在2017年失败,原因仅在于:

错误C2784:'未知类型的std :: operator-(const std :: move_iterator <_RanIt>&,const std :: move_iterator <_RanIt2>&)':无法推导'const std :: move_iterator <_RanIt>的模板参数&”(来自“ const NodeTableIterator ...”)

内部简单检查即可std::copy显示此错误源:

    const auto _UDest = _Unchecked_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
Run Code Online (Sandbox Code Playgroud)

_Idl_distance真正期望我的迭代器应支持的位置operator -。您知道如何克服这种奇怪的要求吗?

L. *_* F. 6

您需要在类本身内提供五种类型:

template <class Container>
struct NodeTableIterator {
    using iterator_category = /* ... */;
    using value_type = /* ... */;
    using difference_type = /* ... */;
    using pointer = /* ... */;
    using reference = /* ... */;
    // ...
};
Run Code Online (Sandbox Code Playgroud)

或在的自定义专业化范围内std::iterator_traits。否则,标准算法中迭代器类别上的标签分发将无法正常工作。


参考:[iterator.traits] / 1(必须提供中的类型std::iterator_traits

为了仅根据迭代器实现算法,通常需要确定与特定迭代器类型相对应的值和差值类型。因此,要求如果 Iterator是迭代器的类型,则该类型

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::iterator_category
Run Code Online (Sandbox Code Playgroud)

分别定义为迭代器的差异类型,值类型和迭代器类别。另外,类型

iterator_traits<Iterator>::reference
iterator_traits<Iterator>::pointer
Run Code Online (Sandbox Code Playgroud)

应该定义为迭代器的引用和指针类型,即对于迭代器对象,分别a*a和 的类型相同a->。对于输出迭代器,类型

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::reference
iterator_traits<Iterator>::pointer
Run Code Online (Sandbox Code Playgroud)

可以定义为void

[iterator.traits] / 2std::iterator_traits可以从成员类型中生成in 的类型)

如果Iterator有有效的([temp.deduct])的成员类型 difference_­typevalue_­typepointerreference,和 iterator_­categoryiterator_­traits<Iterator>应具备以下为公开访问的成员:

using difference_type   = typename Iterator::difference_type;
using value_type        = typename Iterator::value_type;
using pointer           = typename Iterator::pointer;
using reference         = typename Iterator::reference;
using iterator_category = typename Iterator::iterator_category;
Run Code Online (Sandbox Code Playgroud)

否则,iterator_­traits<Iterator>不得有以上任何名称的成员。