在C ++中声明指向decltype方法的指针

时间:2016-11-18 10:20:40

标签: c++ pointers gcc methods clang

clanggcc之间存在一些差异。其中之一就是他们如何对待方法的指针。给出以下代码:

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一样清晰。

最明显的方法是编写一些将thismethod_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;')不是类,命名空间或枚举

有没有办法建立这样的宏?如果没有,还有其他方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:3)

T &不是在这种情况下可用的类型(如评论中指出的那样,它仍然是一种类型),它是一个参考。您可以使用std::remove_reference<...>::typedocumentation)删除引用,改为获取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\
    )