如何判断模板参数可转换为算术类型?C++模板特化实现问询
如何判断模板参数是否为算术类型?
你想要的是仅当模板参数T本身属于C++标准定义的算术类型时,test<T>::value返回true,自定义类哪怕能隐式转换为int/double也不生效对吧?这里有几种简单靠谱的实现方式:
方法一:直接用标准库的std::is_arithmetic
这是最简洁也最准确的方案,C++标准库已经为我们提供了std::is_arithmetic类型特性,它会直接判断类型是否是算术类型(涵盖所有整数类型和浮点类型),完美匹配你的需求:
#include <type_traits> #include <iostream> template<typename T> struct test : std::is_arithmetic<T> {}; // 测试用例 class a{ int a; double b; }; int main() { std::cout << test<int>::value << std::endl; // 输出1(true) std::cout << test<double>::value << std::endl; // 输出1(true) std::cout << test<a>::value << std::endl; // 输出0(false) std::cout << test<char>::value << std::endl; // 输出1(true,char属于算术类型) std::cout << test<unsigned long>::value << std::endl; // 输出1(true) return 0; }
这个实现完全满足你的要求:自定义类a会返回false,所有算术类型都会返回true,而且不需要自己写复杂的SFINAE逻辑。
方法二:手动结合整数/浮点类型判断
如果你想手动实现类似逻辑,可以结合std::is_integral和std::is_floating_point——毕竟算术类型的定义就是整数类型加浮点类型的集合:
#include <type_traits> #include <iostream> template<typename T> struct test : std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value> {}; // 测试用例同上
这个实现和std::is_arithmetic的效果完全一致,本质就是标准库is_arithmetic的底层逻辑。
方法三:用SFINAE手动检测算术操作(不推荐,有局限性)
如果你想用SFINAE的方式来实现(也就是你最初设想的void_t特化),可以通过检测类型是否支持算术运算间接判断,但这种方法有明显局限性:如果自定义类重载了operator+之类的算术运算符,会被误判为true。示例代码如下:
#include <type_traits> #include <iostream> // C++17及以上自带std::void_t,C++11/14需要自己定义 template<typename...> using void_t = void; template<typename T, typename = void> struct test : std::false_type{}; // 仅当T能进行加法运算时,匹配此特化 template<typename T> struct test<T, void_t<decltype(std::declval<T>() + std::declval<T>())>> : std::true_type{}; // 测试用例同上
还是更推荐前两种方法,因为它们基于类型本身的分类,不会因为自定义类重载运算符而出现误判。
内容的提问来源于stack exchange,提问作者Tsao Shisong
相关产品推荐
相关产品推荐

