2016-11-18 90 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