shved shved - 14 days ago 5
C++ Question

Declaring pointer to method with decltype in C++

There are some differences between

clang
and
gcc
. One of them is how they treat the pointers to method. Given the following code:

template <typename T_Class, typename T_Ret, typename ... Args>
void store_method(T_Class *object, T_Ret (T_Class::*method)(Args ... args));

class SomeObjectWithPotentiallyLongName {
int commonly_used_method(int var);
void register_method() {
/* The code below is okay for gcc with -std=gnu++11. But clang
* says:
* 'reference to non-static member function must be called' */
store_method(this, commonly_used_method);
/* To make this fine for clang (and also - gcc), I have to
* extend previous line as next */
store_method(this, &SomeObjectWithPotentiallyLongName::commonly_used_method);
}
}


The code above shows the necessity to extend code in many places to make it compiled by clang, while it can be much neat and as clear with gcc.

The most obvious way is to write some macro which would turn
this
and
method_name
to something like
&TypeOfThis::method_name
.

My idea was to use
decltype
:

#define STORE_METHOD(method) store_method(this, (decltype(*this))::method)

void SomeObjectWithPotentiallyLongName::register_method() {
STORE_METHOD(commonly_used_method);
}


But this code yield the following error with
clang
:


'decltype(*this)' (aka 'SomeObjectWithPotentiallyLongName &') is not a class, namespace, or enumeration


Is there any way to build such macro? If not, is there an other way to solve this problem?

Answer

Well T & is not a type that is usable in this context (as pointed out in the comments it is still a type), it's a reference. You can use std::remove_reference<...>::type (documentation) to remove the reference and get the T type instead:

typedef std::remove_reference<decltype(*this)>::type T;

And then use:

T::method
Comments