2016-11-18 91 views
4

clanggcc之间有一些差异。其中之一是他们如何对待方法的指针。考虑下面的代码:在C++中使用decltype声明指针的方法

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

上面的代码表明有必要在很多地方扩展代码,使其通过铛编译,虽然它可以更整齐,用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(*本)'(又名 'SomeObjectWithPotentiallyLongName &')不一个类,命名空间或枚举

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

回答

3

好吧T &不是在这种情况下可用的类型(正如评论中指出的那样,它仍然是一个类型),它是一个参考。您可以使用std::remove_reference<...>::typedocumentation)移除的参照,并得到了T类型,而不是:

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

然后用:

T::method 
+1

'T&'是一种类型。它可能不是你想要的类型,但它是一种类型。 –

+0

是的这个作品。谢谢! – shved

3

您在您的宏错过&。此外decltype可以产生一个合格的引用类型,因此应使用std::decay以除去参考和限定符:

#define STORE_METHOD(method)\ 
    store_method(\ 
     this,\ 
     &std::decay<decltype(*this)>::type::method\ 
    ) 

或者std::decay_t在C++ 14:

#define STORE_METHOD(method)\ 
    store_method(\ 
     this,\ 
     &std::decay_t<decltype(*this)>::method\ 
    ) 
+0

这也适用,但托马斯是第一个。谢谢。 – shved