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

use*_*315 24 c++ standards types numbers

文档std::numeric_limits<T>说它不应该专门针对非基本类型.数字式用户定义类型怎么样?如果我定义了我自己的T表示数值的类型并重载数字运算符,并且表示的信息numeric_limits是有意义的 - 如果我专门numeric_limits针对该类型,会有什么破坏吗?

gha*_*.st 19

简短回答:

来吧,没有什么不好的事情会发生.

答案很长:

C++标准广泛地保护了::stdC++ 11 17.6.4.2.1中的命名空间,但在第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某些类型的特殊化:

非基本标准类型,例如复杂(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 const,T volatileT const volatile.

  • "除非专业化符合原始模板的标准库要求,否则这种专业化会导致未定义的行为." 原始要求仅适用于算术类型,表明用户专业化可能具有未定义的行为. (4认同)

Yol*_*ola 10

举个例子:

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

  • 你真的希望这是一个 `constexpr` 函数 (2认同)