Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
480 views
in Technique[技术] by (71.8m points)

c++ - How do you get the type of a member function

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.

So, I decided to test it

struct S
{
    using Fn = void();
    Fn foo;

    static_assert(std::is_same_v<decltype(foo), Fn>);
};

But its an error at decltype(foo): invalid use of non-static member fucntion.

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>);
};

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The standard explicitly states that you can't do this.

[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) 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) to form a pointer to member ([expr.unary.op]), or

   (2.3) if that id-expression denotes a non-static data member and it appears in an unevaluated operand.

[ Example:

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.

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.

  • Let's assume m is declared as void m(); and it is a member of class S. If decltype(S::m) is valid, then std::add_pointer<decltype(S::m)> should also be valid.
    Considering that member functions have the implicit this parameter, what would this second type be? void (S::*)(), or maybe something like void (*)(S*)? Or even void (*)()? It may be obvious to us that we want void (S::*)(), but knowing that S::m is just a regular function type, why would add_pointer turn it into a pointer-to-member? How could it even differentiate it?

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...