2016-11-18 8 views
4

clanggccの間にはいくつかの違いがあります。それらの1つは、メソッドへのポインタをどのように扱うかです。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となるマクロを書き込むことです。

私の考えはdecltypeを使用することでした:

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

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

しかし、このコード収率次clangとのエラー:

'decltype(*本)'(別名 'SomeObjectWithPotentiallyLongName &')がありませんクラス、名前空間、または列挙型

このようなマクロを構築する方法はありますか?そうでない場合、この問題を解決する別の方法がありますか?

答えて

3

井戸は、この文脈で使用できるタイプではありません(コメントで指摘されているように、それは参考になります)。

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

そして使用します:あなたは、参照を削除し、代わりに Tタイプを取得するために std::remove_reference<...>::typedocumentation)を使用することができます

T::method 
+1

'T&'タイプです。あなたが望むタイプではないかもしれませんが、タイプです。 –

+0

これはうまくいきます。ありがとうございました! – shved

3

あなたのマクロで&を逃しました。もし基準と修飾子を除去するstd::decayを使用すべきであるので、またdecltypeは、修飾された参照型を生じ得る:C++ 14に

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

またはstd::decay_tを:

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

これも機能しますが、トーマスが最初です。ありがとうございました。 – shved

関連する問題