如何获得成员函数的类型 [英] How do you get the type of a member function
问题描述
该问题的灵感来自标准 [class.mem]
The question is inspired by a note in the standard [class.mem]
非静态成员函数的类型为普通函数类型,非静态数据成员的类型为普通对象类型.没有特殊的成员函数类型或数据成员类型.
The type of a non-static member function is an ordinary function type, and the type of a non-static data member is an ordinary object type. There are no special member function types or data member types.
所以,我决定进行测试
struct S
{
using Fn = void();
Fn foo;
static_assert(std::is_same_v<decltype(foo), Fn>);
};
但在decltype(foo)
处出现错误:无效使用非静态成员功能.
如何获取成员函数的类型?还是只是伪造的钞票?
How do you get the type of a member function? Or is the note just bogus?
注意:对数据成员执行此操作是有效的
Note: It is valid to do this to data members
struct U
{
int i;
static_assert(std::is_same_v<decltype(i), int>);
};
注2:我不是在寻找如何通过指向成员的指针来获取类型
Note2: I'm not looking for how to grab the type through a pointer-to-member
template<typename>
struct NotLikeThis;
template<typename C, typename R, typename... Args>
struct NotLikeThis<R (C::*)(Args...)>
{
using type = R(Args...);
};
标准中的注释与此无关.
The note from the standard is irrelevant to this.
推荐答案
标准明确指出您不能执行此操作.
The standard explicitly states that you can't do this.
[expr.prim.id]
2 一个
[expr.prim.id]
2 An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
(2.1) 作为类成员访问的一部分,其中对象表达式引用成员的类 58 或一个类从该类派生的,或者
(2.1) 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
(2.2) 形成指向成员的指针( [expr.unary.op] )或
(2.2) to form a pointer to member ([expr.unary.op]), or
(2.3) 如果 id-expression 表示非静态数据成员,它出现在未评估的操作数中.
(2.3) if that id-expression denotes a non-static data member and it appears in an unevaluated operand.
[示例:
struct S {
int m;
};
int i = sizeof(S::m); // OK
int j = sizeof(S::m + 42); // OK
—结束示例 ]
— end example ]
请注意,我只强调使用 :这是使用表示成员函数的表达式的唯一方法.您想出的其他任何方法都是不正确的.
Note my emphasis on can only be used: 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.
请注意,2.3正是您想要的-在未评估的上下文(即:decltype
)中使用S::m
(m
是成员函数),但是具体来说(我会假设故意)仅适用于 data 成员.
Note that 2.3 is exactly what you want to to - to use S::m
(m
being a member function) in an unevaluated context (i.e.: decltype
), but it specifically (and I would assume deliberately) only applies to data members.
我可以想到至少允许这样做的一种含义(请参阅下文).可能还有更多.
I can think of at least one implication of allowing this (See below). There's probably more.
- 假设
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
会将其变成一个指向成员的指针?它甚至如何区分它?
- Let's assume
m
is declared asvoid m();
and it is a member of classS
. Ifdecltype(S::m)
is valid, thenstd::add_pointer<decltype(S::m)>
should also be valid.
Considering that member functions have the implicitthis
parameter, what would this second type be?void (S::*)()
, or maybe something likevoid (*)(S*)
? Or evenvoid (*)()
? It may be obvious to us that we wantvoid (S::*)()
, but knowing thatS::m
is just a regular function type, why wouldadd_pointer
turn it into a pointer-to-member? How could it even differentiate it?
这篇关于如何获得成员函数的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!