Will there be a concept for arithmetic types in C++ standard library?
Disclaimer: I'm not a C++ expert, and not deeply familiar with C++ concepts. So the following answer might be a bit derailing, but I thought about this concept in a different context, and think that some of the points here may be relevant.
You did not exactly say what the concept should convey, beyond the example that it should cover integral and floating point types. But from a more theoretical, conceptual point of view, "arithmetics" could be applied much more broadly - even though the word arithmetics implies that it is about numbers.
Intuitively, one could expect the concept to convey the following:
The type in question supports the basic arithmetic operations, +
, -
, *
and /
, and the result type of these operations is the same as the type of the operands. From a quick websearch, this idea seems to be formalized roughly like that:
self operator+(self const& x, self const& y);
self operator−(self const& x, self const& y);
self operator∗(self const& x, self const& y);
self operator/(self const& x, self const& y);
However, there is more that is required for a proper arithmetic:
- the there must be a closure of the elements under the given operation
- there must be a neutral element of addition (
0
) - there must be a neutral element of multiplication (
1
) - there must be an additive inverse for each element (
-x
) - there must be a multiplicative inverse for each element (
/x
- except for the neutral element of addition...)
You see that a can of worms is opened here. These constraints are already hard or impossible to enforce for integral types, as there may be no additive inverse, particularly for unsigned
types. For floating point types, the special cases grow out of hand quickly, due to +/-inf
and most importantly: NaN
. All this does not yet even consider the limited precision of floating point arithmetic.
Going one step further down the theoretical rabbit hole: The concept of arithmetics should probably be a special form (or combination) of general algebraic concepts. For example, it is perfectly fine to consider the unsigned integer types as a cyclic group, and to some extent, some structures involving integral or floating point types have properties that would be associated with a ring.
So a concept of arithmetics that goes beyond saying that it is "either float or int" would certainly be interesting, but has many caveats. Trying to formulate the concept cleanly, so that it may, for example, also be applied to complex numbers or similar structures, is difficult. And if one tried to define this, one would certainly also like to cover other algebraic structures like groups or rings (e.g. for matrices or polynomials) or even vector spaces...
Some people tried this, at least: A quick websearch revealed a Techcnical Report: Fundamental Algebraic Concepts in Concept-Enabled C++ that tackles some of these ideas, including arithmetics, and points out the difficulties that are associated with that. It's from 2006, though - there might be newer research, based on the concepts as they found their way into the standard.
Is there any good reason why it's not there? Or is there any proposal to add it?
There isn't any proposal to add it, but I would expect to see an NB comment that just proposes template <typename T> concept arithmetic = std::is_arithmetic_v<T>;
† (which doesn't guarantee that C++20 will have this concept, merely that at least it will be considered).
The standard library concepts were added by the Ranges proposal and were driven by needs in algorithms for certain concepts. integral
comes up a lot, but I guess arithmetic
never did and so it just never got added. If you look at, say, N4382 (from early 2015), you can see that Integral
(and SignedIntegral
and UnsignedIntegral
) were there from the very beginning... whereas even FloatingPoint
got added way later. (by P0631, in July 2019... and even the paper that added the floating point concept didn't make any mention of arithmetic
)
†Of course, then you get into the fun question of whether it should be based on strictly that type trait or should it be template <typename T> concept arithmetic = integral<T> || floating_point<T>;
so that both the integral
and floating_point
concepts subsume arithmetic
. Probably? Maybe?