是否可以将 std::numeric_limits 专门<T>用于用户定义的类数字类?

is it ok to specialize std::numeric_limits<T> for user-defined number-like classes?

本文关键字:用户 用于 gt 定义 数字 numeric limits 专门 lt 是否 std      更新时间:2023-10-16

std::numeric_limits<T>的文档说它不应该专门用于非基本类型。那么类似数字的用户定义类型呢?如果我定义了自己的类型T,它表示一个数值并重载数值运算符,并且numeric_limits表示的信息对它有意义——如果我将numeric_limits专一化为该类型,会有什么破坏吗?

简短回答:

去吧,不会发生坏事的。

长答:

c++标准在c++ 11 17.6.4.2.1中广泛地保护::std命名空间,但在第1段和第2段中特别允许您的情况:

c++程序的行为是未定义的,如果它将声明或定义添加到命名空间std或命名空间STD中的命名空间,除非另有指定。程序可以添加模板专门化对于任何标准库模板,仅当声明依赖于用户定义类型时,才将其命名为STD并且专门化满足原始模板的标准库需求,并且不显式禁止。

[…程序可以显式实例化标准库中定义的模板,只有当声明依赖于用户定义类型的名称,并且实例化满足标准库要求

旧的c++ 03在17.4.3.1/1中有类似的定义:

c++程序向命名空间std或命名空间添加声明或定义是未定义的在命名空间STD内,除非另有指定。程序可以为任何对象添加模板专门化标准库模板到命名空间std。标准的这种专门化(全部或部分)标准库模板导致未定义的行为,除非声明依赖于的用户定义名称外部链接,除非专门化满足原始模板的标准库要求。

在通过了这个基本的垫脚石之后,您已经指出,c++ 03 18.2.1/4禁止对某些类型的::std::numeric_limits进行专门化:

非基本标准类型,如complex(26.2.2),不能有专门化。

最新的c++ 11 18.3.2.1/4有一个稍微不同的措辞:

非算术标准类型,如complex<T>(26.4.2),不能有专门化。

然而,这两个公式都允许非标准类型的专门化,T就是,因为你自己定义了它(正如@BoPersson已经在评论中指出的)。

警告

c++ 11 18.3.2.3/1提示你应该(但不要求你)确保你的专门化具有所有成员。

同样,您可能希望确保您的专门化不违反c++ 11 18.3.2.3/2:

cv限定类型cv T上的numeric_limits特化的每个成员的值必须相等到非限定类型t的专门化对应成员的值

这基本上意味着,如果你想为T专门化它,你也应该为T constT volatileT const volatile专门化它。

举个例子:

namespace std {
    template<> class numeric_limits<Temperature> {
    public:
       static Temperature lowest() {return Temperature(-273.15f);};
       // One can implement other methods if needed
    };
}