2016-05-05 12 views
0

_Callable __fが(特定の非静的メンバー関数へのポインタ)memberfuncAであるかどうかをテストします。
私は__f == &MyClass::memberfuncAでそれをテストできますが、以下の例のようにmemberfuncBを取得しないとコンパイルエラーになります。
私はstd :: is_convertibleを使ってキャストがコンパイルされるようにしようとしましたが、それは動作しませんでした。 typeid()と同じです。特定のメンバー関数で呼び出し可能ポイントをテストする場合

#include <type_traits> 
#include <typeinfo> 

class A {}; 
class B {}; 

class MyClass { 
public: 
    MyClass() { 
     A a; 
     B b; 
     push_exec(&MyClass::memberfuncA, this, a); 
     push_exec(&MyClass::memberfuncB, this, b); 
    } 

    template<typename _Callable, typename... _Args> 
    void push_exec(_Callable&& __f, _Args&&... __args) 
    { 
     // Test if typeid is the same 
     if(typeid(__f) == typeid(&MyClass::memberfuncA)) 
      // Test if types are castable 
      if(std::is_convertible<typeof __f, typeof &MyClass::memberfuncA>::value) 
       // Test if __f is actually pointing to a specific member function (compiler error) 
       if(__f == &MyClass::memberfuncA) 
        return; 
    } 

    void memberfuncA(A a) { } 
    void memberfuncB(B b) { } 
}; 

int main() { 
    MyClass mc; 
} 

コンパイラの出力が

g++ --std=gnu++11 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/callable_test.d" -MT"src/callable_test.o" -o "src/callable_test.o" "../src/callable_test.cpp" 
../src/callable_test.cpp: In instantiation of ‘void MyClass::push_exec(_Callable&&, _Args&& ...) [with _Callable = void (MyClass::*)(B); _Args = {MyClass* const, B&}]’: 
../src/callable_test.cpp:13:49: required from here 
../src/callable_test.cpp:24:24: error: comparison between distinct pointer types ‘void (MyClass::*)(B)’ and ‘void (MyClass::*)(A)’ lacks a cast [-fpermissive] 
       if(__f == &MyClass::memberfuncA) 
         ^
../src/callable_test.cpp:24:24: error: cannot convert ‘__f’ from type ‘void (MyClass::*)(B)’ to type ‘void MyClass::*’ 
../src/callable_test.cpp:24:24: error: cannot convert ‘&MyClass::memberfuncA’ from type ‘void (MyClass::*)(A)’ to type ‘void MyClass::*’ 
make: *** [src/callable_test.o] Error 1 

私は__f == &MyClass::memberfuncAかどうかを確認することができますどのように任意のアイデアですか?それはコンパイルの問題ではなく、実行時エラーだから

+0

これは問題ではありませんが、2つのアンダースコア( '__f')で始まる名前は、実装に予約されています。それらを使用しないでください。 –

+0

アプローチの「部分テンプレートの特殊化」を参照してください。 – Peter

答えて

0

あなた本当に__f&MyClass::memberfuncを比較したい場合は、std::is_convertibleでチェックvoid *

  if(((void*)__f) == ((void*)&MyClass::memberfuncA)) 
       return; 

に彼らをキャストすることができますが動作しません。つまり、std::is_convertiblevaluefalseであっても、コンパイラは次のようにしてコンパイルしようとします。if

SFINAEでstd::is_convertibleを試してみることもできます。このような何か(EDIT:修正バージョンが):

template<typename _Callable, typename... _Args> 
    typename std::enable_if<true == std::is_convertible<_Callable, void (MyClass::*)(A)>::value, void>::type push_exec(_Callable && __f, _Args && ... __args) 
    { 
     // do something 
    } 

template<typename _Callable, typename... _Args> 
    typename std::enable_if<false == std::is_convertible<_Callable, void (MyClass::*)(A)>::value, void>::type push_exec(_Callable && __f, _Args && ... __args) 
    { 
     // do something else 
    } 
+0

std :: enable_ifは宣言される前に__fを知る必要があります... 'void *'が機能します! 「void(MyClass :: *)(A)」から「void *」への変換[-Wpmf-conversions] どういうわけか、警告を避けることはできますか? – Laurenz

+0

@Laurenz警告は、あなたがやるべきことは悪い考えであることを示唆しています。おそらく、ソリューションを再設計する時でしょうか? –

+0

@Laurenz:私はRichard Hodgesに同意します:それは悪い考えです(私の「本当に」の意味でした)。 'std :: enable_if'について...申し訳ありませんが、昨日私は急いでいました(私は変数を使用しましたか?それは信じられません)。今私は例を修正しました。 – max66

関連する問題