Description
Full name of submitter: Joshua Cranmer
Reference (section label): [conv.rank]
Issue description:
Suppose we have a system where double
, long double
, and _Float64
or std::float64_t
all use the same underlying floating-point semantics. Under C23 (taken from draft N3096), the common real floating-point type is determined by first using the interchange type (i.e., _Float64
), then long double
, and then double
). Under C++23, [conv.rank] specifies that long double
and double
are different ranks (per p2.2), with std::float64_t
is in the same rank as double
(per p2.5) and a higher subrank than double (per 3).
Under C's rules, then, if you were to add long double
and _Float64
, the _Float64
would be the result. But under C++, long double
is the result, because the long double
rank wins out over _Float64
's rank. It is not clear that this result was intentional. P1467R6 and later revisions all have a C compatibility section, where these paragraphs appear:
Previously, there was also a difference in usual arithmetic conversions. This proposal and C have always agreed on the results of a binary operator when at least one of the operands is a floating-point type and the two types have different representations. However, when the two operands were different floating-point types with the same representation, this paper proposed that
double + std::float64_t
(assuming they have the same representation) would have typedouble
, while in C,double + _Float64
has type_Float64
. The rationale for the C rules is that if a user buys into the fixed-layout types explicitly, we should preserve that decision through expressions and library function calls.
This matter was discussed during an SG22 meeting, and a consensus was reached that this paper should instead adopt the C rules; now, with this revision, the result of
double + std::float64_t
isstd::float64_t
.
Records of the relevant SG22 meeting can be found at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2835.pdf, which confirm that this is accurate.
A subsequent followup to the CFP mailing list by the author of P1467 was sent to ask about this case, and if C would change its rules to make long double
+ _Float64
yield long double
instead here: http://mailman.oakapple.net/pipermail/cfp-interest/2021-October/002256.html. The CFP reply indicated no desire in C to change, and the subsequent CFP telecon also affirmed that (see https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2876.pdf for meeting minutes). However, none of the further discussions of the paper in C++ appear to have observed this incompatibility with C, although the topic of mapping to double
or long double
was discussed during CWG telecons (specifically the one on 2022-03-25).
It is not clear if the incompatibility between C and C++ with regards to the arithmetic conversions here was intentional.
Suggested resolution:
Change [conv.rank]p2.5 to
An extended floating-point type with the same set of values as more than one cv-unqualified standard floating-point type has a rank equal to the highest rank among such types.