我已经阅读了一些关于SFINAE的文章,但找不到我的案例的解决方案.这就是我想要做的:
#include <type_traits> struct CByteArray {}; struct HLVariant { HLVariant() {} HLVariant(const HLVariant&) {} HLVariant(const CByteArray&) {} }; template <typename T> struct Serializer { static inline typename std::enable_if<std::is_pod<T>::value,CByteArray>::type serialize(const T& value) { static_assert(std::is_pod<T>::value,"Not a POD type"); return CByteArray(); } static inline typename std::enable_if<!std::is_pod<T>::value,CByteArray>::type serialize(const T& value) { return Serializer<HLVariant>::serialize(HLVariant(value)); } }; template <> struct Serializer<HLVariant> { static inline CByteArray serialize(const HLVariant& value) { return CByteArray(); } }; int main() { int i = 0; Serializer<int>::serialize(i); Serializer<CByteArray>::serialize(CByteArray()); Serializer<HLVariant>::serialize(HLVariant()); return 0; }
但是,当然,我收到错误C2039:’type’:不是’std :: enable_if< false,CByteArray>‘的成员
如何实现我想要的?
此外,是否可以以某种方式重新组织串行器,以便可以隐式推导出模板参数 – Serializer :: serialize(i);而不是Serializer< int> :: serialize(i);?
解决方法
要使用std :: enable_if< condition>,您必须在条件的模板中.一种选择是声明辅助成员函数模板serialize_t
template <typename T> struct Serializer { template<bool is_pod> // template over condition static typename std::enable_if< is_pod,CByteArray>::type serialize_t(const T& value) { return CByteArray(); } template<bool is_pod> static typename std::enable_if<!is_pod,CByteArray>::type serialize_t(const T& value) { return Serializer<HLVariant>::serialize(HLVariant(value)); } static CByteArray serialize(const T& value) { return serialize_t<std::is_pod<T>::value>(value); } }; template<> struct Serializer<HLVariant> { static CByteArray serialize(const HLVariant&) { return CByteArray(); } };
或者,您可以直接在类模板的范围内应用SFINAE:
template<typename T,typename = void> struct Serializer; template<> struct Serializer<HLVariant> { static CByteArray serialize(const HLVariant&) { return CByteArray(); } }; template<typename T> struct Serializer<T,typename std::enable_if<is_pod<T>::type> { static CByteArray serialize(const T&) { return CByteArray(); } }; template<typename T> struct Serializer<T,typename std::enable_if<!is_pod<T>::type> { static CByteArray serialize(const T&value) { return Serializer<HLVariant>::serialize(HLVariant(value)); };
或者你可以摆脱类Serializer并通过模板函数直接声明:
inline CByteArray serialize(const HLVariant&) { return CByteArray(); } template<typename T> inline typename enable_if<std::is_pod<T>::value,CByteArray>::type serialize(const T&) { return CByteArray(); } template<typename T> inline typename enable_if<!std::is_pod<T>::value,CByteArray>::type serialize(const T&value) { return serialize(HLVariant(value)); }
BTW,C 14定义了非常有用的别名
template<bool C,typename T> using enable_if_t = typename enable_if<C,T>::type;
但是你当然可以这样做.这样可以一直避免繁琐的typename和:: type.