2017-10-19 14 views
2

私はVS2015 Update 3を使用しています。呼び出し可能オブジェクトの戻り値の型に基づいて特殊化したい関数があります。呼び出し可能オブジェクトがファンクタである場合、すべてが期待通りに機能します。呼び出し可能なオブジェクトが関数または関数ポインタである場合、オーバーロードされた関数の特殊化に失敗します。私は何かが分からないように感じるが、私はSFINAEで何もしていない。関数ポインタの特殊化に失敗しました

特殊化の原因となっているのは何ですか?代替障害が置換の即時コンテキスト内で唯一の障害であるため、この

template <typename T> 
struct S 
{ 
    T mOp; 
    template <typename = void> 
    typename std::enable_if< 
     std::is_same< 
      std::remove_cv_t< 
       std::remove_reference_t< 
        decltype(mOp()) 
       > 
      >, 
      void 
     >::value 
    >::type func() 
    { 
     std::cout << "bool" << std::endl; 
    } 
    template <typename = void> 
    typename std::enable_if< 
     std::is_same< 
      std::remove_cv_t< 
       std::remove_reference_t< 
        decltype(mOp()) 
       > 
      >, 
      bool 
     >::value 
    >::type func() 
    { 
     std::cout << "void" << std::endl; 
    } 
}; 

template <typename T> 
auto createS(T&& t) 
{ 
    return S<T>{ t }; 
} 

void vfunc() 
{ 
} 
bool bfunc() 
{ 
    return true; 
} 
struct vfunctor 
{ 
    void operator()() 
    { 
    } 
}; 
struct bfunctor 
{ 
    bool operator()() 
    { 
     return true; 
    } 
}; 

void func() 
{ 
    createS(bfunc).func();  // Fails to specialize func() 
    createS(vfunc).func();  // Fails to specialize func() 
    createS(vfunctor{}).func(); 
    createS(bfunctor{}).func(); 
} 

答えて

5

どれも、働かない - あなたはすぐに、関数テンプレートパラメータに依存しないコンテキストでSFINAEしようとしています。 func()の制約は、クラスのテンプレートパラメータに基づいており、ローカル関数テンプレートのパラメータではないため、単なるハードエラーです。

これを行う最も簡単な方法は、タグディスパッチによるものです。ただ、過負荷、タグ型にdecltype(mOp())をラップして:

template <class T> struct tag { }; 

template <typename T> 
struct S 
{ 
    T mOp; 

    void func() { 
     func_impl(tag<std::decay_t<decltype(mOp())>>{}); 
    } 

    void func_impl(tag<bool>) { std::cout << "bool\n"; }   
    void func_impl(tag<void>) { std::cout << "void\n"; }   
}; 

あなたには、いくつかの理由でSFINAEフレンドリーそのものであることをfunc()が必要な場合は、その後、あなたは、元の1アウトだけで偽物に新しいテンプレートパラメータを導入することができます:これは、様々なfunc_impl過負荷の後の宣言を表示させていること

template <class..., class U=T> 
auto func() 
    -> decltype(func_impl(tag<std::decay_t<std::invoke_result_t<U>>>{})) 
{ 
    return func_impl(tag<std::decay_t<std::invoke_result_t<U>>>{}); 
} 

注意。

関連する問題