【发布时间】:2017-07-26 16:25:51
【问题描述】:
我目前正在尝试使用 VC++ 编译器编译一个简单的 SFINAE 结构。我的版本(根据 cl 命令)是
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86
这段代码在 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);
}
但在 Microsoft 的编译器上会失败。不,我不能使用另一个版本,我坚持使用我现在正在使用的版本。我总是在这个编译器上使用 SFINAE 减轻成功,但我不知道如何轻松“修复”这段代码。
预期的结果是得到一个调试字符串表示的东西,如果它有一个getDebugString,使用这个方法,如果它是一个基类型,使用一个自定义方法,否则,只打印类型的名称。
您认为我的 Visual Studio 版本有什么方法可以实现这一目标吗?
【问题讨论】:
-
前两个重载的目的是什么?一个是返回
spString的方法,另一个是返回std::string的方法? -
就是处理类型有方法getDebugString的情况,用它代替默认的fallback方法
-
关于编辑:std::string 从未被提及,我们不使用 std::string 出于一些旧的原因。还有一种方法适用于指向对象的指针或类似对象的指针,另一种适用于直接实例
-
没有注意到您在一种情况下使用了
.,在另一种情况下使用了->- 为了便于阅读,最好在第二种情况下使用T *v。 -
您使用的是哪个版本的 clang?我可以让这段代码用 clang 编译,这看起来很正常,因为这里没有办法选择前两个重载之一而不是第三个。
标签: c++ templates visual-c++ metaprogramming sfinae