2011-01-26 15 views
4
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <utility> 
#include <functional> 
#include <type_traits> 

struct X {}; 
struct Y {}; 

__int8 f(X x) { return 0; } 
__int16 f(...) { return 0; } 

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) { 
    std::cout << "In call with f available"; 
    f(t); 
    return 0; 
} 

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) { 
    std::cout << "In call without f available"; 
    return 0; 
} 

int main() { 
    Y y; X x; 
    call(y); 
    call(x); 
} 

をSFINAEをコンパイルすることはできません、それはenable_if<false, int>::typeをインスタンス化することができないということである、ここでSFINAEの非常に簡単に使用しているようだが、コンパイラはエラーをスローします。助言がありますか?どうやら、このコードはGCCでうまくコンパイルされています(どのバージョンになっているのか尋ねませんでした)。は、Visual Studioで10

編集:このコードは、だから私はbugarooneyさまで、このいずれかをチョークして完全に満足している微

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <utility> 
#include <functional> 
#include <type_traits> 

struct X {}; 
struct Y {}; 

__int8 f(X x) { return 0; } 
__int16 f(...) { return 0; } 

template<typename T> struct call_helper { 
    static const int size = sizeof(f(T())); 
}; 

template <typename T> typename std::enable_if<call_helper<T>::size == sizeof(__int8), int>::type call(T const& t) { 
    std::cout << "In call with f available"; 
    f(t); 
    return 0; 
} 

template <typename T> typename std::enable_if<call_helper<T>::size == sizeof(__int16), int>::type call(T const& t) { 
    std::cout << "In call without f available"; 
    return 0; 
} 

int main() { 
    Y y; X x; 
    call(y); 
    call(x); 
} 

をコンパイルします。

+0

@DeadMG:errrorとは何ですか? call(y)かcall(x)かテンプレート定義(どちらか)のどちらかであるかどうかを確認してください。 –

+0

Comeauは 'error:オーバーロードされた関数のインスタンスがありません。 Visual C++では、最初のオーバーロードの定義に似ていません。面白い。 –

+0

@DeadMG:3番目の関数を試してください。__int16 call(int i){return 0; }それからそれは多分可変引数呼び出し(...)だとわかるでしょう –

答えて

2

これはVS2010で正しくコンパイルされ、正しく動作します。ダビデの示唆を使って修正されました。

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <utility> 
#include <functional> 
#include <type_traits> 

struct X { 
    typedef X is_x; 
    }; 
struct Y {}; 

__int8 f(X x) { return 0; } 
__int16 f(...) { return 0; } 

template < class T > 
struct test { 
    enum { result = sizeof(f(T())) }; 
    }; 

template <typename T> 
typename std::enable_if< test<T>::result == sizeof(__int8), int>::type call(T const& t) { 
    std::cout << "In call with f available" << std::endl; 
    f(t); 
    return 0; 
} 

template < typename T > 
typename std::enable_if< test<T>::result == sizeof(__int16), int>::type call(T const& t) { 
    std::cout << "In call without f available" << std::endl; 
    return 0; 
} 

int main() { 

    Y y; X x; 
    call(y); 
    call(x); 
} 
+0

残念ながら、このコードは 'sizeof'ハックの目的をすべて否定しています。これは' decltype'がない場合にこれらの型を比較す​​るためにここで使用されています。 –

+0

私はVS2010を持っていませんが、 'test'を次のように書き直すのはどうでしょうか?' template struct test {static const int value = sizeof(f(T())); }; 'それで、' enable_if'でそれを 'typename enable_if < test :: value == sizeof(__ int8)、int> ...'のように使用してください。 –

+0

@DavidRodríguez - dribeasうまくいくように見えます。宣言型が必要です。私はまだ結果を得るために別の型を調べるためにコンパイラを強制する理由を説明できません。 – MerickOWA

関連する問題