阅读时[expr.prim.id] , 人们会看到这一点
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
- if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
我不清楚上面的项目符号仅适用于数据成员这一事实。凭直觉,我希望以下内容格式正确:
#include <type_traits>
using func = int();
class bar {
func foo; // This is valid, and not the subject of the question
};
static_assert(std::is_same<decltype(bar::foo), func>::value, "No Symmetry!");
但是 decltype()
甚至在静态断言被检查之前就已经是错误格式了。
我是否遗漏了一些歧义?
最佳答案
Is there some ambiguity I'm missing?
事实上,作为该成员函数声明的一部分添加了大量类型信息。
虽然 func
肯定可以用来声明该成员,但故事并没有就此结束。一旦声明了成员,它的类型就完成了。这涉及添加一些其他内容,例如 cv-qualifers 和 ref-qualifiers。在 foo
的情况下,所有默认的隐式都已确定,并且它们成为 bar::foo
类型的一部分。由 [dcl.fct]/8 指定:
The return type, the parameter-type-list, the ref-qualifier, the cv-qualifier-seq, and the exception specification, but not the default arguments, are part of the function type.
没有办法在上面的foo
声明中明确指定它们(尽管它们可能被添加到func
),但它们通常可以被添加:
class bar {
int foo() const volatile &&;
};
它们是函数类型的一部分,如果它们出现,decltype(bar::foo)
应该解决它们(如果我收集正确,即使它们没有出现)。
当我们尝试评估 decltype(bar::foo)
时,const volatile &&
去了哪里?
- 它应该被忽略吗?那是可以做到的。但是丢失类型信息很少是一件好事。
- 我们是否应该保留它,并且类型
decltype
评估为指向成员函数的指针?
这也行得通,但现在它不同于数据成员在未计算的上下文中命名时的行为方式。我们引入了差异。 - 是否应该保留它并将类型解析为其他类型?也许像
int(foo const volatile&&)
或int() const volatile &&
(另一种形式的函数类型)?这打破了人们期望的对称性,并且再次成为数据成员的差异。
没有简单或明显的方法可以让它始终有效。因此,与其让一个用途有限的功能变得复杂,不如将其视为格式错误。
关于c++ - 我们不能在未评估的上下文中命名非静态成员函数有什么原因吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47263793/