C++ 使用std::enable_if on模板函数返回类型利用SFINAE编译错误
下面的代码C++ 使用std::enable_if on模板函数返回类型利用SFINAE编译错误,c++,templates,sfinae,C++,Templates,Sfinae,下面的代码 #include <type_traits> struct CByteArray {}; struct HLVariant { HLVariant() {} HLVariant(const HLVariant&) {} HLVariant(const CByteArray&) {} }; template <typename T> inline typename std::enable_if<!std
#include <type_traits>
struct CByteArray {};
struct HLVariant {
HLVariant() {}
HLVariant(const HLVariant&) {}
HLVariant(const CByteArray&) {}
};
template <typename T>
inline typename std::enable_if<!std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
{
return serialize(HLVariant(value));
}
template <typename T>
inline typename std::enable_if<std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
{
return CByteArray();
}
template <>
inline CByteArray serialize(const HLVariant& value)
{
return CByteArray();
}
int main()
{
serialize(0);
serialize(CByteArray());
serialize(HLVariant());
return 0;
}
#包括
结构CByteArray{};
结构HLVariant{
HLVariant(){}
HLVariant(const HLVariant&){}
HLVariant(constcbyterarray&){
};
模板
内联类型名称std::enable_if::value,CByteArray>::类型序列化(常量T&value)
{
返回序列化(HLVariant(value));
}
模板
内联typename std::enable_if::type serialize(const T&value)
{
返回cbyteraray();
}
模板
内联CByteArray序列化(常量HLVariant和值)
{
返回cbyteraray();
}
int main()
{
序列化(0);
序列化(CByteArray());
序列化(HLVariant());
返回0;
}
触发编译错误C2794:“type”:不是MSVC 2013中“std::enable_if”的任何直接或间接基类的成员。但是,它在ideone中确实起作用:
这里怎么了
MSVC 2010、2012和2013中的错误是相同的。在我看来还可以,但我可以通过从序列化的最后重载中删除模板来修复它。没有必要使它成为一个完全专业化的时候,一个正常的超载将做
编辑:其他有效方法是提供仅匹配HLVariant
(并进一步限制其他专业不再匹配HLVariant
,以避免歧义)的模板专业化
这应该做到:
#包括
#包括
结构CByteArray{};
结构NonPod{public:inta;private:intb;};
结构HLVariant{
HLVariant(){}
HLVariant(const HLVariant&){}
HLVariant(constcbyterarray&){
HLVariant(const NonPod&){}
};
模板
内联typename std::enable_if::type serialize(const T&value)
{
std::cout::value,CByteArray>::类型序列化(const T&value)
{
我可以打赌错误是“MSVC 2013”吗如果你暗示MS编译器的质量不如GCC,那么你就不能再脱离事实了。@ VioletGiraffe在C++语言的顺应性方面。MS编译器落后于其他领域。它有其他优点,但是不要自欺欺人地说C++语言符合性。MSVC 2013的更新在VS14中是如何工作的?CTP@Yakk:riilight,它不是C++14 compliant还没有。不管怎样,我们能回到主题上来吗?我知道你在那里做了什么…问题是,在我的实际代码中,这样的重载会导致一大堆错误,因为非模板重载优先(IIRC),和HLvariant
可以通过非显式构造函数从大约50种不同的类型构造。换句话说,将调用serialize
的错误版本。用户定义的转换应该不如模板精确匹配好?好的,听起来您想要一个只匹配HLVa的模板专业化riant
(并防止其他专业匹配HLVariant
,以避免歧义)。我将更新…@BenHymers:是的,这完全正确。我将在将来添加更多专业。因此专业化不起作用,但如果仍然起作用,则使用enable\u隐藏?我已经运行了一个简短的检查-它在MSVC中编译。
#include <type_traits>
#include <iostream>
struct CByteArray {};
struct NonPod {public: int a; private: int b;};
struct HLVariant {
HLVariant() {}
HLVariant(const HLVariant&) {}
HLVariant(const CByteArray&) {}
HLVariant(const NonPod&) {}
};
template <typename T>
inline typename std::enable_if<std::is_same<T, HLVariant>::value && !std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
{
std::cout << "serialize non-pod variant\n";
return CByteArray();
}
template <typename T>
inline typename std::enable_if<!std::is_same<T, HLVariant>::value && !std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
{
std::cout << "serialize non-pod non-variant\n";
return serialize(HLVariant(value));
}
template <typename T>
inline typename std::enable_if<std::is_pod<T>::value, CByteArray>::type serialize(const T& value)
{
std::cout << "serialize pod\n";
return CByteArray();
}
int main()
{
std::cout << "int:\n";
serialize(0);
std::cout << "CByteArray:\n";
serialize(CByteArray());
std::cout << "HLVariant:\n";
serialize(HLVariant());
std::cout << "NonPod:\n";
serialize(NonPod());
}