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