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

kcc*_*qzy 27 c++ this decltype c++11

显然clang think 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 { /* ... */ }; }
};
Run Code Online (Sandbox Code Playgroud)

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

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

kcc*_*qzy 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&,T其类型e;
  - 否则,decltype(e)是类型e.
说明符的操作数 decltype是未评估的操作数(第5条).

5.1.1一般[expr.prim.general]

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

之前对§9.3.2的引用是一个错误,因为它涉及成员函数的主体,如下面MWid的评论中所指出的.

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

所以看起来gcc是错的.


gx_*_*gx_ 14

this是一个prvalue,所以decltype(this)应该始终是普通的X*(或/ ).添加似乎是GCC中的一个错误(使用g ++ 4.8.1测试),它只发生在类模板(不是"普通"类)中,而只发生在尾部返回类型内(不在成员体内)功能):演示.这似乎是在GCC 4.9(实验)中修复的,你可以在这里测试一下.X cv*cv X*const&