问题的灵感来自标准[class.mem]
中的注释非静态成员函数的类型是普通函数类型,非静态数据成员的类型是普通对象类型。没有特殊的成员函数类型或数据成员类型。
所以,我决定测试它
struct S
{
using Fn = void();
Fn foo;
static_assert(std::is_same_v<decltype(foo), Fn>);
};
但在decltype(foo)
处出现错误:无效使用非静态成员函数。
如何获得成员函数的类型?或者笔记是假的?
注意:对数据成员执行此操作
是有效的struct U
{
int i;
static_assert(std::is_same_v<decltype(i), int>);
};
注意2:我没有找到如何通过指向成员的指针获取类型
template<typename>
struct NotLikeThis;
template<typename C, typename R, typename... Args>
struct NotLikeThis<R (C::*)(Args...)>
{
using type = R(Args...);
};
标准中的注释与此无关。
答案 0 :(得分:0)
该标准明确指出您不能执行此操作。
[expr.prim.id]
2 id-expression表示类的非静态数据成员或非静态成员函数只能使用:
(2.1) 作为class member access的一部分,其中对象表达式引用成员的类 58 或从该类派生的类,或者
(2.2) 形成指向成员([expr.unary.op])的指针,或者
(2.3) 如果该id-expression表示一个非静态数据成员,并且它出现在未评估的操作数中。
[示例:
struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK
-结束示例 ]
请注意,我对的强调只能使用:这些是可以使用表示成员函数的表达式的唯一方法。您想出的其他任何方法都是错误的。
请注意,2.3正是您想要的-在未评估的上下文(即S::m
)中使用m
(decltype
是成员函数),但是它特别是(并且我认为故意)仅适用于 data 成员。
我可以想到至少允许这样做的一种含义(请参阅下文)。可能还有更多。
m
被声明为void m();
,并且它是类S
的成员。如果decltype(S::m)
有效,则std::add_pointer<decltype(S::m)>
也应该有效。this
参数,
第二种是什么? void (S::*)()
或其他内容
像void (*)(S*)
一样?甚至void (*)()
?对于我们来说,显而易见的是我们想要void (S::*)()
,但是知道S::m
只是一个常规函数类型,为什么add_pointer
会把它变成一个指向成员的指针?它甚至如何区分它?