Using std :: enable_if for the return type of a template function to use SFINAE - compilation error

Following code

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

runs compilation error C2794: 'type' : is not a member of any direct or indirect base class of 'std::enable_if<false,CByteArray>' in MSVC 2013. However, it works in ideone: enter the link description here

What is the mistake here?

In MSVC 2010, 2012, and 2013, the error is the same.

+2
source share
1 answer

This looks fine to me, but I can fix it by removing template<> from the final serialize overload. No need to do this with full specialization under normal overload!

EDIT: What else works is to provide a template specialization that only HLVariant (and further restricts other specializations to no longer match HLVariant to avoid ambiguity).

This should do it:

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()); } 
+2
source

Source: https://habr.com/ru/post/977703/


All Articles