Pas*_* By 7 c++ language-lawyer
这个问题的灵感来自标准中的一个注释[class.mem]
非静态成员函数的类型是普通函数类型,非静态数据成员的类型是普通对象类型.没有特殊的成员函数类型或数据成员类型.
所以,我决定测试一下
struct S
{
using Fn = void();
Fn foo;
static_assert(std::is_same_v<decltype(foo), Fn>);
};
Run Code Online (Sandbox Code Playgroud)
但它的错误在于decltype(foo)
:无效使用非静态成员fucntion.
你如何获得成员函数的类型?或者笔记是假的?
注意:对数据成员执行此操作是有效的
struct U
{
int i;
static_assert(std::is_same_v<decltype(i), int>);
};
Run Code Online (Sandbox Code Playgroud)
注2:我不是在寻找如何通过指向成员的指针来获取类型
template<typename>
struct NotLikeThis;
template<typename C, typename R, typename... Args>
struct NotLikeThis<R (C::*)(Args...)>
{
using type = R(Args...);
};
Run Code Online (Sandbox Code Playgroud)
标准中的注释与此无关.
The standard explicitly states that you can\'t do this.
\n\n\n\n\n[expr.prim.id]
\n \n2 An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
\n \n(2.1)\n as part of a class member access in which the object expression refers to the member\'s class58 or a class derived from that class, or
\n \n(2.2) \n 形成指向成员的指针 ( [expr.unary.op] ),或
\n\n(2.3) \n 如果该id 表达式 denotes a non-static data member and it appears in an unevaluated operand.
\n\n[ 示例:\n
\n\nRun Code Online (Sandbox Code Playgroud)\n\nstruct S {\n int m;\n};\nint i = sizeof(S::m); // OK\nint j = sizeof(S::m + 42); // OK\n
\xe2\x80\x94 结束示例\n ]
\n
注意我强调的是只能使用: Those are the only ways that you can use an expression denoting a member function. Any other way you can come up with is ill-formed.
\n\n请注意,2.3 正是您想要的 - 在未评估的上下文中使用S::m
(m
作为成员函数)(即:)decltype
,但它具体(并且我会故意假设)仅适用于数据 members.
我至少可以想到允许这样做的一个含义(见下文)。可能还有更多。
\n\nm
被声明为void m();
并且它是 class 的成员S
。如果decltype(S::m)
有效,那么std::add_pointer<decltype(S::m)>
也应该有效。this
参数,\n这第二种类型是什么?void (S::*)()
,或者可能是\n之类的东西void (*)(S*)
?甚至void (*)()
?对我们来说,我们想要的可能是显而易见的void (S::*)()
,但知道这S::m
只是一个常规函数类型,为什么还要add_pointer
turn it into a pointer-to-member? How could it even differentiate it?