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

c++, numbers, standards, types

Solution

Short answer:

Go ahead, nothing bad will happen.

Long answer:

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:

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.

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

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.

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:

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

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

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

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).

Caveats

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

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

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.

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`.

Problem

The documentation of `std::numeric_limits<T>` says it should not be specialized for non-fundamental types. What about number-like user-defined types? If I define my own type `T` which represents a numeric value and overloads numeric operators, and for which the information represented by `numeric_limits` makes sense -- will anything break if I specialize `numeric_limits` for that type?

Original source