2012-07-02 15 views
6

decltypeとSFINAE enable_ifを使用するのは簡単ではないようです。私はgoenable_ifで3種類の方法で書こうとしました。それらのすべてがコンパイラエラーで失敗しました(GCCの文字通り「エラー: '事は' fooのメンバーではありません」とインスタンス化コンテキスト)。 enable_ifも機能を排除する機会を得る前に発生する必要がdecltype -declitypeとenable_ifを混ぜる

#include <type_traits> 

struct foo { 
    enum { has_thing = false }; 
}; 

struct bar { 
    enum { has_thing = true }; 
    static int thing() { return 0; } 
}; 

template <typename T> 
struct Test { 
    /*auto go(typename std::enable_if<T::has_thing, int>::type=0) 
    -> decltype(T::thing()) { 
    return T::thing(); 
    }*/ 

    /*typename std::enable_if<T::has_thing, decltype(T::thing())>::type go() { 
    return T::thing(); 
    }*/ 

    template <bool B=T::has_thing, typename std::enable_if<B, int>::type = 0> 
    auto go() -> decltype(T::thing()) { 
    return T::thing(); 
    } 
}; 

int main() { 
    Test<bar> b; 
    Test<foo> f; 
} 

私は問題が何であるかを見ることができます。残っている問題は、回避して同様の動作を得る方法です。 enable_ifで使用する特性をhas_thingと書くことにせずにこれを行う簡単で一般的な方法はありますか?

G ++ 4.7とclang ++ 3.0の両方でテストされています。

+1

コンパイルエラーを投稿できますか?また、コンパイラのバージョンが役に立ちます。私は経験からコンパイラがこの部門ではまだ非常にバグだと言うことができます。 –

答えて

5

go方法は、テンプレート方式であればSFINAEは動作します:

template <typename T> 
struct Test { 
    template <class U = T> 
    auto go() -> decltype(U::thing()) { 
    return T::thing(); 
    } 
}; 

あなたはまた、has_thing値を使用することができますが、必要はありません

template <class U = T, typename std::enable_if<U::has_thing, int>::type = 0> 
auto go() -> decltype(U::thing()) { 
    return T::thing(); 
} 

その後:

SFINAEは、上記の例でそのの世話をしますから、それを行うには
int main() { 
    Test<bar> b; 
    Test<foo> f; 

    b.go(); // Works! 
    f.go(); // Fails! 
} 
+0

ありがとう、私はTが3番目のバージョンでもSFINAEに参加していなかったということを知りました私は試しました。 'has_thing'値は実際のコードでは論理値ではありません - 異なる実装の性能特性に基づいて同じコードの異なるバージョンを選びます – Flexo

0

SFINAEは機能しません。 goの機能はで、のテンプレートではないため、SFINAEは適用できません。それ以外の場合は、decltypeで正常に動作するはずです(実際にはhas_thingフラグは必要ありません)。

例:これは正常に動作します(と他のオーバーロードとうまく演じている):

template <class U> 
auto go(Test<U> t) 
    -> decltype(U::thing()) { 
    return U::thing(); 
} 
+1

質問の3番目のバージョン(コメントは付けられていません)は間違いなくテンプレートですが、TがSFINAEに参加していないことがわかります。 ( 'has_thing'はここの例です - 実際のコードでは' thing 'の存在だけでなくパフォーマンスの特性も説明します – Flexo