2017-07-26 10 views
0

現在、VC++コンパイラを使用して単純なSFINAE構造体をコンパイルしようとしています。 (CLコマンドに応じて)私のバージョンは SFINAE with VC++コンパイラ

// Example program 
#include <iostream> 
#include <string> 
#include <typeinfo> 

struct spString 
{ 
    template <class... T> 
    spString format(T...) { return spString(); } 
    const char* c_str() { return nullptr; } 

    spString operator+(spString) { return spString(); } 
    spString operator+(const char*) { return spString(); } 
}; 

struct debuggable 
{ 
    spString getDebugString() { return spString(); } 
}; 

void fromFloat(spString, float&) {} 
void fromInt(spString, int&) {} 


template <class T> inline auto from(T v) 
    -> decltype(v.getDebugString(), spString()) 
{ 
    return v.getDebugString(); 
} 
template <class T> inline auto from(T v) 
    -> decltype(v->getDebugString(), spString()) 
{ 
    spString r; 
    r.format("%u (%s)", (size_t) v, v->getDebugString().c_str()); 
    return r; 
} 
template <class T> inline spString from(T v) 
{ 
    return spString("(") + typeid(T).name() + " instance)"; 
} 
template <> inline spString from(float _v   ) { spString _d; fromFloat   (_d, _v); return _d; } 
template <> inline spString from(int _v   ) { spString _d; fromInt   (_d, _v); return _d; } 
//other base types 

int main() 
{ 
    debuggable x{}; 

    from(0); 
    from(0.f); 
    from(x); 
} 

打ち鳴らす

Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86 

このコードはコンパイル罰金ですが、Microsoftのコンパイラに失敗します。私は別のバージョンを使用することができないと私は今使用していると私は立ち往生しています。私はいつもこのコンパイラでSFINAEの成功を緩和しましたが、このコードを簡単に "修正"する方法はわかりません。

期待される結果は、getDebugStringを持っている場合は何かのデバッグ文字列表現を取得することです。このメソッドを基本型の場合はカスタムメソッドを使用し、そうでない場合は型名を出力します。

私のVisual Studioでこれを達成する方法はありますか?

+0

2つの最初のオーバーロードの目的は何ですか?一つは 'spString'を返すメソッドで、もう一つは' std :: string'を返すメソッドです。 – Holt

+0

型がgetDebugStringメソッドを持ち、デフォルトのフォールバックメソッドの代わりに使用するケースを処理することです – Nyashes

+0

編集について:std :: stringは決して言及されていません。いくつかの古い理由でstd :: stringを使用しません。また、メソッドの一つは、オブジェクトへのポインタやポインタのようなオブジェクトに適用され、もう一つはインスタンスを指示するために適用されます – Nyashes

答えて

1

ここでは、VC 19.00.24215.1でテストしたいことがあります。

template <typename T> 
auto has_getDebugString_impl(int) -> 
    decltype(void(std::declval<T>().getDebugString()), std::true_type{}); 

template <typename T> 
auto has_getDebugString_impl(...) -> std::false_type; 

template <typename T> 
struct has_getDebugString: decltype(has_getDebugString_impl<T>(0)) { }; 

std::enable_ifと組み合わせる:

ヘルパーテンプレートはgetDebugString()を検出する

template <class T> 
inline std::enable_if_t < has_getDebugString<T>::value, spString > from(T v) { 
    return v.getDebugString(); 
} 

template <class T> 
inline std::enable_if_t < has_getDebugString<T>::value, spString > from(T *v) { 
    spString r; 
    r.format("%u (%s)", (size_t)v, v->getDebugString().c_str()); 
    return r; 
} 
template <class T> 
inline std::enable_if_t < ! has_getDebugString<T>::value, spString > from(T v) { 
    return spString("(") + typeid(T).name() + " instance)"; 
} 

、特定の種類の過負荷(専門ではないテンプレート):

inline spString from(float _v) { spString _d; fromFloat(_d, _v); return _d; } 
inline spString from(int _v) { spString _d; fromInt(_d, _v); return _d; } 

これはきれいなコードではなく、そこより簡単な方法であることが、私はVCでいくつかの問題に対処しなければならなかったことがあります...

注:デフォルトのテンプレートパラメータ内enable_ifを使用することができます

template <class T, class = std::enable_if_t<has_getDebugString<T>::value>> 
inline spString from(T v) { 
    return v.getDebugString(); 
} 
+0

おかげで申し訳ありませんが、今はちょっと遅れているコンピュータを見つけることができました。 – Nyashes

関連する問題