2012-08-17 18 views
6

コンパイルされない次のコードがあります。 これは私がRetのが何であるかの種類に応じて、メンバーの方法で専門を持ちたい引数テンプレートメソッドenable_if特化

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // ... 
} 

typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // .... 
} 

を取るテンプレートクラスに2つの関数です。

誰か知っていますか?

答えて

7

SFINAEは、テンプレート以外の機能(メンバーまたは非メンバー)では機能しません。

Kerrek SBが指摘しているように、非メンバ関数テンプレートを作成すると機能します。あるいは、Xeoが指摘するように、デフォルトのテンプレート引数を持つメンバ関数テンプレートを作成することもできます。

しかし、これは2つのstd::enable_ifの条件が重複していないため、です。 int(異なる)に異なるオーバーロードを追加する場合は、うまくスケーリングできないことがわかります。

#include<type_traits> 

template<typename Ret> 
class Foo 
{ 
public: 
    void _on_dispatched() 
    { 
     // tag dispachting: create dummy of either std::false_type or std::true_type 
     // almost guaranteed to be optimized away by a decent compiler 
     helper_on_dispatched(std::is_void<Ret>()); 
    } 

private: 
    void helper_on_dispatched(std::false_type) 
    { 
     // do stuff for non-void 
    } 

    void helper_on_dispatched(std::true_type) 
    { 
     // do stuff for void 
    } 
}; 

int main() 
{ 
    Foo<void>()._on_dispatched(); 
    Foo<int>()._on_dispatched(); 
    return 0; 
} 
+1

:しかし、あなたは内の別のテンプレートをこのテンプレートをパックすることができます。 :) http://liveworkspace.org/code/fd6e5383610d4e0d8fb17c5497991355 – Xeo

+1

@Potatoswatter:実際には、いいえ、それは冗談ではありませんでした。リンクを参照すると、戻り値の型だけが実行可能かどうかを判断する、まったく同じシグネチャの関数を完全に細かく設定することができます。 :Pまた、 'std :: is_void ()'を使うだけで、 'std :: true_type'か' std :: false_type'のどちらかから派生する型の特性が必要です。 – Xeo

+1

Btw、[メンバ関数をC++ 11の既定のパラメータを持つテンプレートにすることができます](http://liveworkspace.org/code/781d94df5499998947217970c1aebf2a)。 – Xeo

3

SFINAEは、テンプレートのみで動作します:あなたが何をしたいかに応じて、タグ派遣は一般的にあなたが派遣したい複数の選択肢を持つSFINAEより良いスケール。あなたのコードは、小さな変更でコンパイルさせることができます。

template <typename Ret> 
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

template <typename Ret> 
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

使用法:

auto q = _on_dispatched<int>(); 

それは演繹ではありませんので、あなたはもちろん、機能の戻り値の型を推論することはできません。オーバーロードの1が通話時にのみ実行可能なものであれば、あなたがすることができ

template <typename T> 
struct Foo 
{ 
    // insert templates here, maybe privately so 

    T bar() { return _on_dispatched<T>(); } 
}; 
+0

メンバ関数の 'template '、rhalbersmaの答えに関する私のコメントを見てください。 – Xeo

+0

@ Xeo:あなたは ''と書かなくてもいいですか?もちろん :-) –

関連する問題