0
votes

Consider the code:

#include <type_traits>

struct CByteArray {};
struct HLVariant {
    HLVariant() {}
    HLVariant(const HLVariant&) {}
    HLVariant(const CByteArray&) {}

    };

template <typename T>
inline CByteArray serialize(const typename std::enable_if<true, T>::type& value)
{
    return serialize(HLVariant(value));
}

template <typename T>
inline CByteArray serialize(const typename std::enable_if<false, T>::type& value)
{
    return CByteArray();
}

template <>
inline CByteArray serialize(const HLVariant& value)
{
    return CByteArray();
}

int main()
{
    serialize(0);
    serialize(CByteArray());
    serialize(HLVariant());

    return 0;
}

Microsoft Visual Studio 2013 gives the following error:

C2912: explicit specialization 'CByteArray serialize(const HLVariant &)' is not a specialization of a function template

error C2783: 'CByteArray serialize(const std::enable_if::type &)' : could not deduce template argument for 'T'

The error suggests that there's no template <typename T> CByteArray serialize(const T&); function visible to the compiler, and I don't understand why. Note that I'm simply using true and false for enable_if condition for testing purposes here.

I've also tried this way instead (enable_if on return type instead of argument):

    template <typename T>
inline typename std::enable_if<true, CByteArray>::type serialize(const T& value)
{
    return serialize(HLVariant(value));
}

template <typename T>
inline typename std::enable_if<false, CByteArray>::type serialize(const T& value)
{
    return CByteArray();
}

Now the error is:

C2039: 'type' : is not a member of 'std::enable_if<false,CByteArray>'
1
I think if you do it with structure spécialization it will work... (working on it)CollioTV
For SFINAE, the condition should depend of a template parameter.Jarod42
template <> inline CByteArray serialize(const HLVariant& value) Since you don't explicitly specify the template arguments, the compiler will have to deduce them (from the function parameter type). But that's no possible since for both serialize templates, T is in a non-deduced context.dyp
std::enable_if<false, CByteArray>::type Since there is no type dependent on a template parameter, no substitution takes place here, therefore the error does not occur during substitution (=> hard error, no SFINAE).dyp

1 Answers

2
votes

typename std::enable_if<true, T>::type is not deductible in your context (which T should the compiler test, it may be an infinite type for the general case).

You may use instead:

template <typename T>
inline
typename std::enable_if</*your condition depending of T*/, CByteArray>::type
serialize(const T& value)
{
    // Your code
}