简体   繁体   English

带有VC ++编译器的SFINAE

[英]SFINAE with VC++ compiler

I'm currently trying to compile a simple SFINAE structure with VC++ compiler. 我目前正在尝试使用VC ++编译器编译一个简单的SFINAE结构。 My version (according to the cl command) is 我的版本(根据cl命令)是

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

this code compiles fine on clang 此代码可以在clang上正常编译

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

but will fail on Microsoft's compiler. 但在Microsoft的编译器上将失败。 Noe that I can't use another version and I'm stuck with the one I'm using right now. 不,我不能使用其他版本,而我现在使用的是版本。 I always had mitigated success with SFINAE on this compiler but I don't see how to easily "fix" this code. 我一直在使用SFINAE来减轻此编译器的成功,但看不到如何轻松地“修复”此代码。

the expected result is to get a debug string representation of something, if it has a getDebugString, use this method, if it's a base type, use a custom method, otherwise, just print the type's name. 预期的结果是获取某事的调试字符串表示形式,如果它具有getDebugString,请使用此方法,如果它是基本类型,请使用自定义方法,否则,只需打印该类型的名称即可。

Do you see any way to achieve that with my version of visual studio? 您看到用我的Visual Studio版本实现这一目标的任何方法吗?

Here is the way to do what you want - tested with VC 19.00.24215.1. 这是您想要做的方法-已在VC 19.00.24215.1中进行了测试。

Helper template to detected getDebugString() : 检测到的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)) { };

Combined with std::enable_if : 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)"; 
}

And overload (not specialized template) for specific types: 以及针对特定类型的重载(不是专门的模板):

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

This is not the prettiest code, and there may be more straightforward way, but I had to deal with some issue in VC... 这不是最漂亮的代码,可能还有更直接的方法,但是我不得不处理VC中的一些问题...

Note: You can use enable_if inside a default template parameter instead of as a return type if you want: 注意:如果需要,可以在默认模板参数内使用enable_if而不用作返回类型:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM