c++ - 迭代器需求满足

标签 c++ iterator language-lawyer c++14

考虑以下类:

template <class T>
struct X {
    T& operator*() & { return t; }
    T& operator*() && = delete; 
    X& operator++() { return *this; }
    T t;
};

这个类是否满足 C++ 标准对迭代器概念的要求? 此类的对象是可递增和可取消引用的。但右值对象的取消引用是被禁止的。

int main() {
    X<int> x;
    *x; // ok
    *X<int>(); // fail. But is it really necessary for Iterator by Standard?
}

最佳答案

严格阅读标准; [iterator.iterators]/2 (§24.2.2/2)确实暗示 X 类型符合迭代器的条件;

...a and b denote values of type X or const X

...r denotes a value of X&...

A type X satisfies the Iterator requirements if:

  • X satisfies the CopyConstructible, CopyAssignable, and Destructible requirements ([utility.arg.requirements]) and lvalues of type X are swappable ([swappable.requirements]), and

  • the expressions in Table (below) are valid and have the indicated semantics.

    • *r (r is dereferenceable)
    • ++r (returns X&)

给定代码;

template <class T>
struct X {
    T& operator*() & { return t; }
    T& operator*() && = delete; 
    X& operator++() { return *this; }
    T t;
};
int main()
{
    X<int> x;
    ++x;
    int i = *x;
    X<int> y(x);
    using std::swap;
    std::swap(x, y);
}

当然看起来确实满足这些要求。

然而,故事还在继续,迭代器 概念,如上定义,并未列为标准中的迭代器类别之一 §24.2.1/2 ;

This International Standard defines five categories of iterators, according to the operations defined on them: input iterators, output iterators, forward iterators, bidirectional iterators and random access iterators...

他们都定义了一个操作*a and *r++ X 类型编译失败;

int j = *x++; // fails to compile even with the inclusion of the post increment operator
const X<int> xc {};
int ic = *x1; // no const overloads

要在定义的类别之一中使用迭代器,它需要包含更多成员以取消引用 const 值、左值和右值、后增量等。在 spirit of the standard 中;

Iterators are a generalization of pointers that allow a C++ program to work with different data structures (containers) in a uniform manner.

此处针对重载成员和运算符的指导是,可以/应该添加它们以强制遵守并优化(如果可能)通用指针语义的实现——而不是禁止语义;限制语义可能会产生意想不到的后果。

关于c++ - 迭代器需求满足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35680976/

相关文章:

C++ Alt-Tab 钩子(Hook)

Java Set迭代器,删除元素安全吗?

c++ - std::reverse_iterator 如何在开始之前保留一个?

c++ - 使用 std::tie() 和赋值的评估顺序

c - 在没有适当原型(prototype)的情况下调用 printf 会调用未定义的行为吗?

c++ - 为什么此代码在使用可变数组大小时不会生成错误?

c++ - 如何使用新的 Visual Studio 2013 预览版构建 boost ?

c++ - 为什么不允许通过检索到的指向其数据的指针来修改字符串?

c++ - 具有不同比较功能的 map 的通用算法

c++ - 无法创建由 "Parent"链接的元素列表