迭代器要求满意

时间:2016-02-28 09:47:02

标签: 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 ++标准对Iterator概念的要求? 此类的对象是可递增和可解除引用的。但是禁止取消引用右值对象。

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

2 个答案:

答案 0 :(得分:2)

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

  

... ab表示Xconst X

类型的值      

... r表示值X& ...

     

如果符合以下条件,X类型满足迭代器要求:

     
      
  • X满足CopyConstructibleCopyAssignableDestructible要求([utility.arg.requirements]),类型X的左值可以交换([swappable.requirements] ])和
  •   
  • 表(下面)中的表达式是有效的,并具有指示的语义。

         
        
    • *rr可解除引用)
    •   
    • ++r(返回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);
}

当然确实似乎满足了这些要求。

然而,故事仍在继续,上面定义的 Iterator 概念未被列为标准§24.2.1/2中的Iterator类别之一;

  

本国际标准定义了五类迭代器,根据它们定义的操作:输入迭代器,输出迭代器,前向迭代器,双向迭代器和随机访问迭代器......

它们都定义了X类型无法编译的操作*a and *r++;

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; < / p>

  

迭代器是指针的泛化,它允许C ++程序以统一的方式处理不同的数据结构(容器)。

这里对重载成员和运算符的指导是它们可以/应该被添加以强制执行合规并优化(如果可能)广义指针的语义的实现 - 不禁止语义;限制语义可能会产生意想不到的后果。

答案 1 :(得分:1)

嗯,标准没有说明rvalue引用的迭代器。甚至没有识别其成员因引用类型而重载的迭代器。但是你的代码似乎可以接受为iterator *,因为在定义迭代器的要求时......

引用最新C++14 standard draft 24.2.2 部分(重点是我的)

  

24.2.2.2 :如果出现以下情况,则类型X满足迭代器要求:

     

- X满足   CopyConstructible,CopyAssignable和Destructible要求   类型X的(17.6.3.1)和左值是可交换的(17.6.3.2),并且

     

- 表106中的表达式是有效的,并具有指示的语义。

     
      
  • * r:r是可解除引用的

  •   
  • ++ r:r可递增

  •   

除此之外,迭代器没有额外的约束。

*原因,假设结果X<typename ...>满足第一个列出的条件