2017-07-26 110 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