目录
[3.为什么主模板全部返回 _Ty()?](#3.为什么主模板全部返回 _Ty()?)
[4.Windows 宏小细节:(min)() / (max)()](#4.Windows 宏小细节:(min)() / (max)())
[6.自定义类型如何实现合法 numeric_limits](#6.自定义类型如何实现合法 numeric_limits)
1.简介
一句话概括:统一查询任意算术类型的数值边界、浮点特性、特殊值(无穷 / NaN)的标准工具类 ,定义在 <limits>,属于 C++ 标准库。
它的实现如下:
cpp
_EXPORT_STD template <class _Ty>
class numeric_limits : public _Num_base { // numeric limits for arbitrary type _Ty (say little or nothing)
public:
_NODISCARD static constexpr _Ty(min)() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty(max)() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty lowest() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty epsilon() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty round_error() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty denorm_min() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty infinity() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty quiet_NaN() noexcept {
return _Ty();
}
_NODISCARD static constexpr _Ty signaling_NaN() noexcept {
return _Ty();
}
};
//char特化:
template <>
class numeric_limits<char> : public _Num_int_base {
public:
_NODISCARD static constexpr char(min)() noexcept {
return CHAR_MIN;
}
_NODISCARD static constexpr char(max)() noexcept {
return CHAR_MAX;
}
_NODISCARD static constexpr char lowest() noexcept {
return (min) ();
}
_NODISCARD static constexpr char epsilon() noexcept {
return 0;
}
_NODISCARD static constexpr char round_error() noexcept {
return 0;
}
_NODISCARD static constexpr char denorm_min() noexcept {
return 0;
}
_NODISCARD static constexpr char infinity() noexcept {
return 0;
}
_NODISCARD static constexpr char quiet_NaN() noexcept {
return 0;
}
_NODISCARD static constexpr char signaling_NaN() noexcept {
return 0;
}
static constexpr bool is_signed = CHAR_MIN != 0;
static constexpr bool is_modulo = CHAR_MIN == 0;
static constexpr int digits = 8 - (CHAR_MIN != 0);
static constexpr int digits10 = 2;
};
前置宏 / 基类说明
_EXPORT_STDMSVC 导出宏:标准库类导出符号,用于 DLL 边界可见性,对外等价于标准std::。_NODISCARDC++17[[nodiscard]]封装,调用函数不接收返回值会触发编译警告,防止忽略极限值。constexpr noexcept编译期可求值、无异常抛出,符合 C++11 常量表达式规范。_Num_base内部基类,存放各类布尔常量:is_signed/is_integer/digits/max_exponent等静态成员,主模板继承复用。
2.每个静态函数标准语义
cpp
template<class _Ty>
class numeric_limits
1.获取类型的极值范围
区分整数、浮点的最大 / 最小取值,替代 C 语言零散宏(INT_MAX/FLT_MIN 等),类型安全、泛型友好:
max():该类型能存的最大值lowest():该类型能存的最小值(负数极限)min():最小正规正数
static constexpr _Ty (min)() noexcept;
括号
(min)是规避 Windowsmin宏冲突经典写法。
示例:
cpp
numeric_limits<int>::max(); // int上限
numeric_limits<double>::lowest(); // double最小负数
2.查询浮点独有的特殊常量
只对浮点有效,用来做数值精度判断、浮点容错逻辑:
epsilon():机器精度,判断浮点数相等的基准denorm_min():最小非规格化小数infinity():正负无穷quiet_NaN()/signaling_NaN():非数字 NaN
3.通过静态常量查询类型属性(继承自 _Num_base)
一堆布尔 / 整型常量,运行期 / 编译期判断类型特征:
- 是否有符号:
is_signed - 是否整数:
is_integer - 有效二进制位数:
digits - 是否支持无穷、NaN、非规格化数等
泛型场景极常用,比如模板分支判断:
cpp
template<typename T>
void func() {
if constexpr (numeric_limits<T>::is_integer) {
// 整数逻辑
} else {
// 浮点逻辑
}
}
4.统一泛型接口,消除 C 宏的缺陷
C 的极限宏是全局宏,不支持模板、容易冲突(Windows min/max 宏污染); numeric_limits<T> 是模板,和类型绑定,泛型代码不用写多套分支适配 int/float/double。
3.为什么主模板全部返回 _Ty()?
numeric_limits 采用模板特化机制:
- 通用主模板:兜底默认实现,任意自定义类型、不支持数值极限的类型都会走这里,全部返回默认零值;
- STL 内部会针对基础数值类型做全特化:
cpp
template<> class numeric_limits<int>;
template<> class numeric_limits<float>;
template<> class numeric_limits<double>;
template<> class numeric_limits<unsigned long long>;
特化版本才会返回真实的极值、无穷、NaN、epsilon 等常量。
示例区分:
cpp
// 匹配全特化,返回真实最大值
std::numeric_limits<int>::max();
// 无特化,走你贴的主模板,返回 T{}(0)
struct MyType {};
std::numeric_limits<MyType>::max();
4.Windows 宏小细节:(min)() / (max)()
Windows 头文件默认定义宏:
cpp
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
如果直接写 min(),预处理器会把 min 替换成宏,编译报错。
加括号写成 (min) 可以屏蔽宏展开,是 MSVC STL 标准兼容写法。
5.标准库对外简化使用(用户层)
用户不用关心内部 _EXPORT_STD、_Ty 下划线内部名,标准写法:
cpp
#include <limits>
#include <iostream>
int main() {
std::cout << std::numeric_limits<int>::max() << '\n';
std::cout << std::numeric_limits<float>::epsilon() << '\n';
std::cout << std::numeric_limits<double>::infinity() << '\n';
return 0;
}
6.自定义类型如何实现合法 numeric_limits
若要让自定义数值类型支持正确极限,不能依赖主模板,必须显式偏特化:
cpp
struct FixedPoint { int val; };
namespace std {
template<>
class numeric_limits<FixedPoint> {
public:
static constexpr FixedPoint max() noexcept { return {9999}; }
static constexpr FixedPoint min() noexcept { return {1}; }
static constexpr FixedPoint lowest() noexcept { return {-9999}; }
// ...其余接口按需实现
static constexpr bool is_integer = true;
};
}
7.总结
- 这是 MSVC STL
std::numeric_limits通用主模板,是所有数值类型的兜底; - 未特化类型调用所有接口只会返回
T{}(零值),无实际极限意义; - 真实整数 / 浮点数极值由库内置全特化版本提供;
(min)/(max)括号是解决 Windows min/max 宏冲突;- 所有接口
constexpr noexcept [[nodiscard]],支持编译期常量计算。