2017-07-26 53 views
0

我目前正在嘗試用VC++編譯器編譯一個簡單的SFINAE結構。我的(根據CL命令)版本SFINAE與VC++編譯器

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

這個代碼編譯罰款鏗鏘

// 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); 
} 

但是無法對微軟的編譯器。 Noe說我不能使用另一個版本,而且我現在正在使用我正在使用的版本。我一直在這個編譯器上減輕了SFINAE的成功,但是我看不到如何輕鬆「修復」這些代碼。

預期的結果是獲得調試字符串表示的東西,如果它有一個getDebugString,則使用此方法,如果它是基本類型,則使用自定義方法,否則僅打印該類型的名稱。

您是否看到過使用我的Visual Studio版本實現這一目標的方法?

+0

這兩個第一次重載的目的是什麼?一個是返回'spString'的方法,另一個是返回'std :: string'的方法? – Holt

+0

它處理的情況下,類型有一個方法getDebugString,並使用它而不是默認的回退方法 – Nyashes

+0

關於編輯:std :: string永遠不會提到,我們不會使用std :: string的一些老的原因。另外一種方法適用於像指向對象的指針或指針,另一種用於指導實例 – Nyashes

回答

1

下面是你想做什麼的方法 - 用VC 19.00.24215.1測試。檢測到的getDebugString()

助手模板:

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結合:

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