阅读[expr.prim.id]时,会看到
表示非静态数据成员或非静态数据的id表达式 只能使用类的成员函数:
- 如果该id-expression表示非静态数据成员,并且它出现在未评估的操作数中。
上述子弹仅适用于数据成员这一事实对我来说并不清楚。直观地说,我希望以下内容形成良好:
#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()
也是不正确的。
是否有一些我不知道的歧义?
答案 0 :(得分:3)
是否有一些我不知道的歧义?
事实上,有很多类型信息被添加为该成员函数声明的一部分。
虽然func
当然可以用来宣告该成员,但故事并未在此结束。声明成员后,它的类型就完成了。这涉及添加其他一些东西,例如 cv-qualifers 和 ref-qualifiers 。在foo
的情况下,确定所有默认的隐式,并且它们成为bar::foo
类型的一部分。由[dcl.fct]/8指定:
返回类型,参数类型列表,引用限定符, cv-qualifier-seq和异常规范,但不是默认规范 参数,是函数类型的一部分。
在foo
的上述声明中无法明确指定它们(尽管它们可能会被添加到func
),但它们可能会被添加:
class bar {
int foo() const volatile &&;
};
它们是函数类型的一部分,decltype(bar::foo)
应该在它们出现时解决它们(如果我正确收集,即使它们没有),也可以解决它们。
当我们尝试评估const volatile &&
时,decltype(bar::foo)
会去哪儿?
decltype
计算为指向成员函数的指针吗?
这也可行,但现在它与数据成员在未评估的上下文中命名时的行为方式不同。我们引入了一个差异。int(foo const volatile&&)
或int() const volatile &&
(另一种函数类型)?这打破了人们期望的对称性,并且再次与数据成员产生差异。 没有简单或明显的方法可以让它始终运作良好。因此,对于看似有限使用的功能而言,不要使问题复杂化,最好将其视为不良形式。
答案 1 :(得分:0)
我是否有一些模棱两可的缺失?
我不这么认为。可能更需要评估非静态数据成员,而不是非静态成员函数。
但是,这个:
static_assert(std::is_same<decltype(bar::foo), func>::value, "No Symmetry!");
没有多大意义。 &bar::foo
的类型不是func*
,而是func bar::*
。并且没有一种方法可以拼写没有指针,因此必须能够评估decltype(bar::foo)
意味着引入全新的类型语法?看起来不值得。
请注意decltype(bar::foo)
不能是func
,因为func
是函数类型,但bar::foo
是成员函数。
答案 2 :(得分:-1)
我没有看到任何理由。
看看这个:
typedef void Func();
Func freeFunction;
struct Foo {
Func memberFunction;
};
freeFunction
的声明是Func freeFunction;
。因此,decltype(freeFunction)
为void()
,即Func
。
使用相同的逻辑,因为Foo::memberFunction
也被声明为Func
,我也希望decltype(Foo::memberFunction)
也是Func
。但事实并非如此,因为这不会编译。
就像int a; decltype(a)
解析为int
一样,即使int a;
是成员,decltype(Foo::memberFunction)
也应该没问题。
注意,也可以处理限定符,它们没有什么特别之处(当然,在这种情况下,Func
只能用于声明非静态成员函数):
typedef void Func() const volatile &&;
struct Foo {
Func memberFunction;
};
在这里,我希望decltype(Foo::memberFunction)
为void() const volatile &&
,因此我可以复制其声明:
struct Bar {
decltype(Foo::memberFunction) myMemFn;
};
引用C ++ 14标准(9.2 / 11):
[注意:非静态成员函数的类型是普通的 函数类型,非静态数据成员的类型是普通的 对象类型。没有特殊的成员函数类型或数据成员 类型。 - 结束说明]
这句话意味着,如果decltype(<member_function>)
返回了一种普通函数,那将是明智的。