且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2021-09-12 05:15:21

简答:

去吧,不会有坏事发生的.

Short answer:

Go ahead, nothing bad will happen.

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

The C++ standard extensively protects the ::std namespace in C++11 17.6.4.2.1, but specifically allows your case in paragraphs 1 and 2:

如果 C++ 程序将声明或定义添加到命名空间 std 或除非另有说明,否则命名空间 std 内的命名空间.程序可以添加模板特化仅当声明依赖于用户定义的类型时,任何标准库模板才能命名空间 std并且专业化满足原始模板的标准库要求并且没有明确禁止.

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

[...] 程序可以显式实例化标准库中定义的模板,仅当声明取决于用户定义类型的名称并且实例化符合标准库要求用于原始模板.

[...] A program may explicitly instantiate a template defined in the standard library only if the declaration depends on the name of a user-defined type and the instantiation meets the standard library requirements for the original template.

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

The older C++03 has a similar definition in 17.4.3.1/1:

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

It is undefined for a C++ program to add declarations or definitions to namespace std or namespaces within namespace std unless otherwise specified. A program may add template specializations for any standard library template to namespace std. Such a specialization (complete or partial) of a standard library template results in undefined behavior unless the declaration depends on a user-defined name of external linkage and unless the specialization meets the standard library requirements for the original template.

在通过这个基本的垫脚石之后,您已经指出,C++03 18.2.1/4 禁止特定类型的 ::std::numeric_limits 特化:

After getting past this fundamental stepping stone, you already pointed out, C++03 18.2.1/4 forbids specializations of ::std::numeric_limits for certain types:

非基本标准类型,例如复杂 (26.2.2),不应有专门化.

Non-fundamental standard types, such as complex (26.2.2), shall not have specializations.

最新的 C++11 18.3.2.1/4 的措辞略有不同:

The more current C++11 18.3.2.1/4 has a slightly different wording:

非算术标准类型,例如 complex<T> (26.4.2),不应有特化.

Non-arithmetic standard types, such as complex<T> (26.4.2), shall not have specializations.

然而,这两种表述都允许对非标准类型进行专门化,T 是,因为你自己定义了它(正如@BoPersson 已经在评论中指出的那样).

Both of these formulations however allow specializations for non-standard types, which T is, since you defined it yourself (as @BoPersson already pointed out in the comments).

C++11 18.3.2.3/1 提示您应该(但不要求您)确保您的专业化拥有所有成员.

C++11 18.3.2.3/1 hints that you should (but does not require you to) ensure that your specialization has all members.

此外,您可能希望确保您的专业化不违反 C++11 18.3.2.3/2:

Also, you may wish to ensure that C++11 18.3.2.3/2 is not violated by your specialization:

在 cv 限定类型 cv T 上的 numeric_limits 特化的每个成员的值应相等为非限定类型 T 上的特化对应成员的值.

The value of each member of a specialization of numeric_limits on a cv-qualified type cv T shall be equal to the value of the corresponding member of the specialization on the unqualified type T.

这实质上意味着,如果您希望将其专门用于 T,您还应该为 T constT volatileT const volatile.

Which essentially means, that if you wish to specialize it for T, you should also do so for T const, T volatile and T const volatile.