C ++中的decltype(this)是什么类型的?

时间:2013-11-16 17:12:44

标签: c++ c++11 this decltype

显然clang认为decltype(this)是指向cv限定类的指针,而gcc认为它是指向cv限定类的指针的 const引用。 GCC只认为decltype(&*this)是指向cv限定类的指针。当它用作模板的类型名称时,这会产生一些影响。考虑一个假设的例子:

template<typename T>
class MyContainer {
    /* ... */
    template<typename ContainerPtr>
    class MyIterator {
        ContainerPtr container;
        /* ... */
    };
    auto cbegin() const
        -> MyIterator<decltype(&*this)> { return { /* ... */ }; }
    auto cend() const
        -> MyIterator<decltype(this)> { return { /* ... */ }; }
};

在此示例中,实现了T的自定义容器。作为容器,它支持迭代器。实际上,有两种迭代器:iteratorconst_iterator。复制这两个代码是没有意义的,因此可以编写一个模板迭代器类,获取指向原始类MyContainer<T> *的指针或指向const版本MyContainer<T> const *的指针。

cbegincend一起使用时,gcc会出错,说它推断出冲突的类型,而clang只是正常工作。

2 个答案:

答案 0 :(得分:17)

好的,这是我在标准(N3337)中找到的内容:

  

7.1.6.2简单类型说明符[dcl.type.simple]

     

4 decltype(e)表示的类型定义如下:
   - 如果e是不明白的 id-expression 或者   未加密级的类成员访问(5.2.5),decltype(e)是类型   由e命名的实体。如果没有这样的实体,或者e   命名一组重载函数,程序格式不正确;
   - 否则,如果e是xvalue,则decltype(e)T&&,其中。{   T的类型为e; - 否则,如果e是左值,   decltype(e)T&,其中Te的类型;
-   否则,decltype(e)e的类型。
操作数   decltype说明符是未评估的操作数(第5条)。

  

5.1.1一般[expr.prim.general]

     

3如果声明声明了成员函数或成员函数   类X的模板,表达式this是类型的prvalue   “可选 cv-qualifer-seq 之间指向 cv-qualifier-seq X的指针   和函数定义成员声明符的结尾,或   声明符的。它不会出现在可选的 cv-qualifier-seq 之前   它不应出现在静态成员的声明中   函数(虽然它的类型和值类别是在一个   静态成员函数,因为它们在非静态成员中   功能)。 [注意:这是因为不会发生声明匹配   直到知道完整的声明者。 - 结束音符]与对象不同   在其他上下文中,*this的表达式不需要是完整的   类型用于成员之外的类成员访问(5.2.5)   功能体。 [注意:只有在此之前声明的类成员   声明是可见的。 - 结束说明]

之前对§9.3.2的引用是一个错误,因为它处理成员函数的 body ,如下面in a comment by MWid所述。

  <德尔>    9.3.2`his`指针[class.this]      1在非静态(9.3)成员函数体中,   关键字`this`是一个prvalue表达式,其值是地址   调用该函数的对象。 a中的“this”类型   类`X`的成员函数是`X *`。如果成员函数是   声明`const`,`this`的类型是`const X *`,如果是成员   函数声明为`volatile`,`this`的类型是`volatile X *`,   如果成员函数声明为`const volatile`,则为   `this`是`const volatile X *`。   

所以看起来gcc错了。

答案 1 :(得分:14)

this prvalue ,因此decltype(this)应该始终是X*(或X cv* / cv X*)。添加const&似乎是GCC中的一个错误(使用g ++ 4.8.1进行测试),该错误只发生在类模板(不适用于“普通”类)且仅< em>在尾部返回类型内(不在成员函数体内):demo。这似乎在GCC 4.9(实验性)中得到修复,您可以测试here