std::is_arithmetic 是 C++ 标准库中用于编译期判断类型是否为算术类型的 type trait,识别所有内置整型(如 int、char、bool)和浮点类型(如 float、double),但不包括指针、引用、数组、类、枚举(C++20 前)、std::complex、void 和 nullptr_t。

std::is_arithmetic 是什么,能判断哪些类型
std::is_arithmetic 是 C++ 标准库中定义在 <type_traits> 头文件里的类型特征(type trait),用于在编译期判断一个类型是否为「算术类型」。它返回的是一个 std::integral_constant<bool, value> 类型,所以实际使用时要取 ::value 或 C++17 起的 ::value_v。
它识别的类型包括:
- 所有内置整型(
int、unsigned long long、char、bool等) - 所有浮点类型(
float、double、long double) - 不包括指针、引用、数组、类、枚举(除非显式特化或 C++23 枚举增强)、
std::complex、void、nullptr_t
注意:std::is_arithmetic<char>::value 为 true,但 std::is_arithmetic<char*>::value 是 false;enum class E {} 默认也不被识别(C++20 前)。
在模板中用 std::is_arithmetic 做 SFINAE 分流
最常见的用途是在函数模板重载或类模板偏特化中,根据参数是否为算术类型启用不同实现。SFINAE 场景下推荐用 std::enable_if_t 配合 std::is_arithmetic_v(C++17)。
立即学习“C++免费学习笔记(深入)”;
template <typename T>
std::enable_if_t<std::is_arithmetic_v<T>, T> safe_add(T a, T b) {
return a + b;
}
<p>template <typename T>
std::enable_if_t<!std::is_arithmetic_v<T>, T> safe_add(T a, T b) = delete;这样调用 safe_add(3, 4) 成功,而 safe_add(std::string{"a"}, std::string{"b"}) 编译失败(不是因为匹配不到,而是被 = delete 显式禁用)。
容易踩的坑:
- 忘记加
_v后缀(如写成std::is_arithmetic<T>而非std::is_arithmetic_v<T>),导致类型不匹配编译错误 - 在非模板上下文中误用(例如对具体类型硬写
static_assert(std::is_arithmetic<int>)),必须用::value或::value_v -
std::is_arithmetic对 cv 限定符不敏感(const int和int结果一致),但对引用/指针敏感——int&不是算术类型
与 std::is_integral、std::is_floating_point 的关系
std::is_arithmetic_v<T> 等价于 std::is_integral_v<T> || std::is_floating_point_v<T>,但它不区分整型和浮点,适合「只要能做 + - * / 就行」的泛化逻辑。
选择依据:
- 只允许整数运算(比如位移、取模)→ 用
std::is_integral - 需要
std::sqrt或精度控制 → 优先std::is_floating_point - 泛型容器元素要求支持四则运算 →
std::is_arithmetic更自然
示例:一个仅接受算术类型的容器构造函数约束
template <typename T>
class NumericVector {
static_assert(std::is_arithmetic_v<T>, "T must be arithmetic");
// ...
};这里若传入 std::complex<double> 会触发静态断言失败,因为 std::complex 不属于标准算术类型族。
C++20 概念写法更清晰,但要注意兼容性
如果项目已用 C++20,可用 std::arithmetic 概念替代繁琐的 enable_if:
template <std::arithmetic T>
T square(T x) { return x * x; }这比传统 SFINAE 更易读,且错误信息更友好。但要注意:
- 概念不能用于偏特化(类模板仍需用
std::enable_if或requires约束主模板) - 某些旧编译器(如 GCC 9 或 Clang 11 之前)不完全支持,生产环境需确认工具链
-
std::arithmetic是对std::is_arithmetic_v的封装,语义完全一致,无额外行为
真正容易被忽略的是:即使类型满足 std::is_arithmetic,也不代表所有运算都合法(比如 bool / bool 在某些上下文中可能被禁止,或 char + char 产生 int)。类型特征只管“是不是”,不管“能不能安全用”。










