You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17如何为类int类型实现符合习惯用法的NaN算术运算

符合C++17习惯的实现方案

C++不允许直接修改原生类型或标准库类型的默认运算符行为,因此轻量强类型包装器是唯一符合规范且简洁的实现方案,一次实现即可同时覆盖int、std::chrono相关类型的需求,完全保留中缀运算符的使用习惯。

核心实现代码

首先定义通用模板类,所有NaN判断和运算符逻辑只需要写一次:

#include <limits>
#include <chrono>
#include <type_traits>

template<typename T, T NanValue = std::numeric_limits<T>::max()>
class NanAware {
    T m_value;
public:
    // 构造函数,默认值为NaN
    constexpr NanAware(T value = NanValue) noexcept : m_value(value) {}

    // 显式转换为原始类型,避免意外隐式转换
    constexpr explicit operator T() const noexcept { return m_value; }
    // 判断是否为NaN
    constexpr bool is_nan() const noexcept { return m_value == NanValue; }

    // 重载加法运算符
    constexpr friend NanAware operator+(const NanAware& lhs, const NanAware& rhs) noexcept {
        if (lhs.is_nan() || rhs.is_nan()) return {};
        return lhs.m_value + rhs.m_value;
    }

    // 重载减法运算符
    constexpr friend NanAware operator-(const NanAware& lhs, const NanAware& rhs) noexcept {
        if (lhs.is_nan() || rhs.is_nan()) return {};
        return lhs.m_value - rhs.m_value;
    }

    // 按需重载 +=、-= 等其他运算符
    constexpr NanAware& operator+=(const NanAware& rhs) noexcept {
        *this = *this + rhs;
        return *this;
    }

    constexpr NanAware& operator-=(const NanAware& rhs) noexcept {
        *this = *this - rhs;
        return *this;
    }
};

适配你需要的类型

只用给模板传入对应参数定义别名即可,不需要重复写运算逻辑:

// 带NaN的int类型,用int最大值作为NaN标记
using NanInt = NanAware<int>;

// 带NaN的微秒级duration
using NanMicroDuration = NanAware<std::chrono::microseconds>;

// 带NaN的system_clock时间点,自定义NaN标记为最大微秒数对应的时间点
using NanTimePoint = NanAware<
    std::chrono::system_clock::time_point,
    std::chrono::system_clock::time_point{std::chrono::microseconds::max()}
>;

使用示例

完全保留原生的中缀运算符写法,和你期望的Ruby使用体验一致:

NanInt a = 42;
NanInt b; // 默认构造即为NaN
NanInt c = a + b; // 运算结果自动为NaN
if (c.is_nan()) {
    // 处理NaN分支
}

// chrono类型使用方式完全相同
NanMicroDuration d1 = std::chrono::microseconds(100);
NanMicroDuration d2;
auto d3 = d1 - d2; // 结果为NaN

额外说明

  • 该实现是零成本抽象,编译器会完全优化掉包装层,性能和原生类型完全一致
  • 只要确保你选的NaN标记不在业务的正常取值范围内,就不会出现逻辑冲突
  • 如果需要支持乘法、除法、比较等其他运算,只需要在模板类中按照相同逻辑重载对应运算符即可

内容的提问来源于stack exchange,提问作者Camille Goudeseune

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:45:02