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

C++ C+;中decltype(this)的类型是什么+;?,c++,c++11,this,decltype,C++,C++11,This,Decltype,显然,clang认为decltype(this)是指向cv限定类的指针,而gcc认为它是指向cv限定类指针的常量引用。GCC只认为decltype(&*this)是指向cv限定类的指针。当它被用作模板的类型名时,这有一些含义。考虑一个假设的例子: template<typename T> class MyContainer { /* ... */ template<typename ContainerPtr> class MyIterator {

显然,clang认为
decltype(this)
是指向cv限定类的指针,而gcc认为它是指向cv限定类指针的常量引用。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 { /* ... */ }; }
};
模板
类霉菌容器{
/* ... */
模板
类迭代器{
集装箱运输集装箱;
/* ... */
};
自动cbegin()常量
->My迭代器{return{/*…*/};}
自动cend()常量
->My迭代器{return{/*…*/};}
};
在本例中,实现了一个自定义容器
T
。作为一个容器,它支持迭代器。实际上,有两种迭代器:
iterator
s和
const\u迭代器
s。为这两个类复制代码是没有意义的,因此可以编写一个模板迭代器类,使用指向原始类的指针
MyContainer*
或指向常量版本
MyContainer const*


cbegin
cend
一起使用时,gcc会出错,说它推导出了冲突的类型,而clang工作得很好。

好的,下面是我在标准()中发现的:

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

4由
decltype(e)
表示的类型定义如下:
-如果
e
是未加密的id表达式或 未授权类成员访问(5.2.5),
decltype(e)
是 由
e
命名的实体的名称。如果没有此类实体,或者如果
e
命名一组重载函数,则程序格式不正确
-否则,如果
e
是一个x值,
decltype(e)
T&
,其中
T
e
的类型
-否则,如果
e
是左值,
decltype(e)
T&
,其中
T
e
的类型
- 否则,
decltype(e)
decltype
说明符是未赋值的操作数(第5条)

5.1.1概述[解释基本概述]

3如果声明声明了成员函数或成员函数
类的模板
X
,表达式
this
是类型的prvalue “指向可选cv限定符seq之间的cv限定符seq
X
”的指针 函数定义、成员声明符或 声明人。它不应出现在可选cv限定符seq之前 且不应出现在静态成员的声明中 函数(尽管其类型和值类别在 静态成员函数,因为它们位于非静态成员中 功能)。[注意:这是因为不进行声明匹配 直到知道完整的声明符。-结束注释]与对象不同 表达式在其他上下文中,
*此
不要求完整 类型用于在成员外部访问类成员(5.2.5) 功能体。[注:仅在 声明可见。-结束注释]

前面提到的§9.3.2是一个错误,因为它涉及成员函数的主体,如下所述

9.3.2“this”指针[class.this] 1在非静态(9.3)成员函数的主体中 关键字'this'是一个prvalue表达式,其值为的地址 为其调用函数的对象。a中“this”的类型 类`X`的成员函数是`X*`。如果成员函数为 声明为'const',如果成员 函数声明为'volatile',this'的类型为'volatile X*`, 如果成员函数声明为“const volatile”,则 `这是常数X*`。
所以看起来gcc是错误的。

这是一个PR值,所以
decltype(this)
应该始终是普通的
X*
(或者
X cv*
/
cv X*
)。添加
const&
似乎是GCC(用g++4.8.1测试)中的一个错误,它只发生在类模板中(不是“普通”类),并且只发生在尾部返回类型中(不是在成员函数体中):。这在GCC4.9(实验版)中似乎是固定的,您可以进行测试。

评估
这个
会给出一个右值。例如,您不能使用地址,如
中的&this
。如果
this
是常量引用,您可以获取地址。
this
X cv*
类型的prvalue,其中
cv
对应于
R my_foo()cv中的
cv
。你确定Clang认为
这个
是一个cv限定指针,而不是指向cv限定
X
的指针吗?@Xeo,对不起,它应该是指向cv限定类的指针。好吧,显然促使我问这个问题的问题是非常具体和本地化的……注意:你最初的引用似乎来自一个旧的草稿(早于标准化之前的最后一份公开草案)。在实际的C++11标准中,7.1.6.2/4的最终措辞略有不同(最接近标准的草案是,基本上是C++11标准+)。因此,我建议进行编辑。但差异对问题没有影响。此答案不适用于问题!
未在函数体中使用,因此§9.3.2与问题无关。规范的相关部分是§5.1.1/3。但无论如何,这是gcc<4.9中的一个缺陷。