std::is_floating_point 是编译期类型判断trait,仅接受类型参数,返回该类型是否为标准浮点类型(float/double/long double及其cv修饰版);不适用于变量、引用、指针、数组或自定义浮点类型,需配合if constexpr和std::is_arithmetic_v等正确分支。

std::is_floating_point 是编译期判断,不能用在运行时变量上
它不是用来检查某个变量值是不是浮点数的函数,而是对类型本身做静态断言。比如你传 int、float、double 这类类型名进去,它返回 true 或 false —— 但必须是类型,不能是变量。
常见错误是写成这样:std::is_floating_point(x)(x 是变量),这会编译失败,因为模板参数期望一个类型,不是值。
- 正确用法只接受类型:
std::is_floating_point<float>::value</float>、std::is_floating_point<t>::value</t> - C++17 起推荐用
std::is_floating_point_v<t></t>,更简洁 - 它对 cv 限定符不敏感:
std::is_floating_point_v<const double></const>仍是true - 对引用、指针、数组等非标量类型返回
false,哪怕底层是浮点型
泛型函数里怎么安全分支处理浮点/整数逻辑?
典型场景是写一个通用数值函数(比如 clamp、lerp、abs),需要对浮点类型启用 epsilon 比较,对整数用精确比较。这时候得靠 if constexpr 配合 std::is_floating_point_v 做编译期分路。
错误做法是用普通 if:分支代码仍会被实例化,如果里面用了浮点专属操作(如 std::numeric_limits<t>::epsilon()</t>),整数类型就会编译报错。
立即学习“C++免费学习笔记(深入)”;
- 必须用
if constexpr,否则无效 - 确保所有分支里的表达式对当前
T都合法;比如整数分支别调std::sin(x) - 示例:
template<typename T> T safe_div(T a, T b) { if constexpr (std::is_floating_point_v<T>) { return std::abs(b) < std::numeric_limits<T>::epsilon() ? T{0} : a / b; } else { return b == T{0} ? T{0} : a / b; } }
std::is_floating_point 对自定义浮点类型返回 false
它只认标准库定义的浮点类型:float、double、long double,以及它们的 cv 修饰版本。像 __float128、half(CUDA/HIP)、或自己写的 FixedPoint,全都不匹配。
这不是 bug,是标准明确限定的行为。如果你的泛型逻辑要覆盖这些类型,不能只依赖 std::is_floating_point。
- 可配合
std::numeric_limits<t>::is_iec559</t>或std::numeric_limits<t>::is_specialized</t>做补充判断 - 更稳妥的是显式特化或使用概念(C++20):
concept Floating = std::is_floating_point_v<t> || is_my_half_v<t>;</t></t> - 注意:
std::numeric_limits<t>::is_iec559</t>对float/double返回true,但对long double可能为false(取决于平台)
和 std::is_arithmetic、std::is_integral 的关系容易混淆
这三个都是类型分类 trait,但范围不同:std::is_arithmetic_v<t></t> 包含整型 + 浮点型;std::is_integral_v<t></t> 只含整型(不含 char 等窄类型?不,char、bool、enum 默认也算,但需看 std::is_integral 定义);而 std::is_floating_point 是严格子集。
常见误用是想“排除整数”,结果写了 !std::is_integral_v<t></t>,却把 std::string、vector<int></int> 也放进去了 —— 这显然不是你想要的数值分支逻辑。
- 若目标只是“浮点或整数”,优先用
std::is_arithmetic_v<t></t>兜底 - 若要精确区分浮点/整数,必须同时用
std::is_floating_point_v<t></t>和std::is_integral_v<t></t>,别省略后者 -
std::is_arithmetic_v<t></t>对std::complex<float></float>返回false,别指望它覆盖复数
if constexpr;自定义浮点类型不会自动被识别 —— 这三点没踩准,编译器很快就会给你发一长串错误。









