这个函数指针的尾返回类型中带有 `this` 是否合法?

11
class C {
  auto (*foo)() -> decltype(this);
};

这段代码可以被GCC、MSVC和Clang编译器接受,但不包括icc。


4
即使 icc 是非法的,但当它成为标准修补程序的下一个目标时,它可能是你唯一的支持。 ;) - Yakk - Adam Nevraumont
GCC和clang即使在-std=c++11模式下也接受此代码,这表明它们的开发人员认为这不是标准C++的扩展。 - zwol
Clang也允许struct X { int (*p)() noexcept(sizeof(this)); };,而GCC则拒绝它。 - cpplearner
1个回答

7

引用n4140(大致上是C++14)[expr.prim.general]:

3 如果一个声明声明了类X的成员函数或成员函数模板,则表达式this是一个prvalue,其类型为“指向cv限定符序列X”的指针,在可选的cv限定符序列和函数定义、成员声明符或声明符的结尾之间。它不应出现在可选的cv限定符序列之前,并且不应出现在静态成员函数的声明中(尽管它的类型和值类别在静态成员函数中与非静态成员函数中定义的一样)。[...]

4 否则,如果一个成员声明符声明了类X的非静态数据成员(9.2),则表达式this是一个prvalue,其类型为“指向X”的指针,在可选的等号或花括号初始化器内。它不应在成员声明符的其他地方出现。

由于您没有声明成员函数或成员函数模板,因此第3点不适用,但这是使代码对于实际声明成员函数的非指针情况有效的方法:尾随返回类型在可选的cv限定符序列和声明符的结尾之间,如const成员函数的定义中所清晰地说明的那样:

auto foo() const -> decltype(this) { }

p4适用于此处。它仅允许this出现在初始化器中。您将其放在其他地方。p3不适用,因此ICC正确拒绝了此操作。


1
你不觉得第一句话的结尾和开头不太匹配吗?我的意思是,在开头只列出了成员函数作为“this”具有某种特定含义的上下文,然而在结尾却假定这样的上下文还包括成员声明符或声明符。或者说有些东西开始是成员函数声明,但最后变成了声明符吗?结尾让我想到p3实际上是适用的。 - user7860670
1
@VTT 不,这只是因为成员函数或成员函数模板声明可能会根据上下文采用函数定义(如果它包含一个定义),成员声明符(如果它在类内出现但没有定义)或声明符(如果它在类外部出现且没有定义)的形式。 - user743382

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接