我试图实现一个将泛型类型转换为字符串的函数.积分类型需要使用std :: to_string(),字符串和字符使用std :: string()和逐个元素的元素转换为使用其他方法之一的字符串(取决于它们的内容).
这就是我所拥有的:
//Arithmetic types template<class T> typename std::enable_if<std::is_arithmetic<T>::value,std::string>::type convertToString(const T& t){ return std::to_string(t); } //Other types using string ctor template<class T> typename std::enable_if<std::__and_<std::__not_<std::is_arithmetic<T>>::type,std::__not_<std::is_same<T,<T,std::vector<typename T::value_type,typename T::allocator_type>>::value >>>::value,std::string>::type convertToString(const T& t){ return std::string(t); } //Vectors template<class T> typename std::enable_if<std::is_same<T,typename T::allocator_type>>::value,std::string>::type convertToString(const T& t){ std::string str; for(std::size_t i = 0; i < t.size(); i++){ str += convertToString(t[i]); } return str; }
解决方法
Oktalist’s回答解释了为什么你的类型特征无法编译.此外,您不应该使用__and_和__not_.这些是保留的,可以在下一个编译器版本中轻松更改.实现这些特征的自己版本很容易(例如,参见
conjunction
的可能实现).
我建议采用完全不同的方法.我们可以使用选择<>使这些情况重载更简单:
template <int I> struct choice : choice<I+1> { }; template <> struct choice<10> { };
通过:
// arithmetic version template <class T> auto convertToStringHelper(T const& t,choice<0> ) -> decltype(std::to_string(t)) { return std::to_string(t); } // non-arithmetic version template <class T> auto convertToStringHelper(T const& t,choice<1> ) -> decltype(std::string(t)) { return std::string(t); } // vector version template <class T,class A> std::string convertToStringHelper(std::vector<T,A> const& v,choice<2> ) { // implementation here } template <class T> std::string convertToString(T const& t) { return convertToStringHelper(t,choice<0>{}); }
这很好,因为你得到的所有SFINAE都没有任何enable_if cruft.