在模板函数返回类型上使用std :: enable_if来利用SFINAE - 编译错误

时间:2014-11-03 14:47:41

标签: 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::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;
}

在MSVC 2013中触发编译错误C2794: 'type' : is not a member of any direct or indirect base class of 'std::enable_if<false,CByteArray>'。但是,它确实在ideone中工作:enter link description here

这里的错误是什么?

MSVC 2010,2012和2013中的错误相同。

1 个答案:

答案 0 :(得分:2)

我看起来不错,但我可以通过从template<>的最终重载中移除serialize来解决此问题。当正常的重载会发生时,无需使它完全专业化!

编辑:还有哪些方法是提供仅与HLVariant匹配的模板专精化(并进一步限制其他专业化不再匹配HLVariant,以避免歧义)。

这应该这样做:

http://ideone.com/0UGkcn

#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());
}