C++之std::numeric_limits介绍

目录

1.简介

2.每个静态函数标准语义

[3.为什么主模板全部返回 _Ty()?](#3.为什么主模板全部返回 _Ty()?)

[4.Windows 宏小细节:(min)() / (max)()](#4.Windows 宏小细节:(min)() / (max)())

5.标准库对外简化使用(用户层)

[6.自定义类型如何实现合法 numeric_limits](#6.自定义类型如何实现合法 numeric_limits)

7.总结


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_STD MSVC 导出宏:标准库类导出符号,用于 DLL 边界可见性,对外等价于标准 std::
  • _NODISCARD C++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) 是规避 Windows min 宏冲突经典写法。

示例:

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]],支持编译期常量计算。
相关推荐
2501_925963381 小时前
Hi3516 + WS73 SDIO Wi-Fi 适配笔记
java·开发语言
CoderYanger1 小时前
视频切割脚本(Python版)
linux·开发语言·windows·后端·python·程序人生·职场和发展
辞旧 lekkk1 小时前
CMake工程指南(一)
linux·运维·服务器·开发语言·qt·学习·萌新
小七在进步2 小时前
数据结构:用栈实现队列
开发语言·数据结构
KaMeidebaby2 小时前
卡梅德生物技术快报|噬菌体筛选:噬菌体筛选工程化优化方案:基于侵染全链条参数调控与水环境应用验证
java·开发语言·人工智能·机器学习·spark
geovindu2 小时前
go: Floyd-Warshall Algorithms
开发语言·后端·算法·golang
CoderYanger2 小时前
视频裁剪+缩放+自动添加水印脚本(Python版)
开发语言·后端·python·程序人生·职场和发展·音视频·学习方法
酷酷的身影2 小时前
Managers/APConfigManager.cs
开发语言·ui·c#
拳里剑气2 小时前
C++算法:优先级队列
开发语言·c++·算法·优先级队列