clang
和gcc
之间存在一些差异。其中之一就是他们如何对待方法的指针。给出以下代码:
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);
}
}
上面的代码显示了在许多地方扩展代码以使其由clang编译的必要性,而它可以非常整洁并且与gcc一样清晰。
最明显的方法是编写一些将this
和method_name
转换为&TypeOfThis::method_name
的宏。
我的想法是使用decltype
:
#define STORE_METHOD(method) store_method(this, (decltype(*this))::method)
void SomeObjectWithPotentiallyLongName::register_method() {
STORE_METHOD(commonly_used_method);
}
但是此代码会因clang
而产生以下错误:
'decltype(* this)'(又名'SomeObjectWithPotentiallyLongName&amp;')不是类,命名空间或枚举
有没有办法建立这样的宏?如果没有,还有其他方法可以解决这个问题吗?
答案 0 :(得分:3)
好T &
不是在这种情况下可用的类型(如评论中指出的那样,它仍然是一种类型),它是一个参考。您可以使用std::remove_reference<...>::type
(documentation)删除引用,改为获取T
类型:
typedef std::remove_reference<decltype(*this)>::type T;
然后使用:
T::method
答案 1 :(得分:3)
您在宏中错过了&
。此外decltype
可能会产生限定引用类型,因此您应该使用std::decay
来删除引用和限定符:
#define STORE_METHOD(method)\
store_method(\
this,\
&std::decay<decltype(*this)>::type::method\
)
或C ++ 14中的std::decay_t
:
#define STORE_METHOD(method)\
store_method(\
this,\
&std::decay_t<decltype(*this)>::method\
)