Rationale for cmath's std::abs(short) -> double
Wed Feb 3 13:25:00 GMT 2016
On 3 February 2016 at 10:57, Jonathan Wakely wrote:
> abs is an oddity though, as it also has integral overloads. The
> proposed resolution for http://wg21.link/lwg2192 suggests it should
> promote to int, although it's not entirely clear.
We could just remove the abs template, but then abs((__int128)0) and
abs((__int<1>)0) would not compile.
If we only had to support C++11 and later we could implement 2192
pretty easily with common_type:
#if __cplusplus >= 201103L
// 2192. Validity and return type of std::abs(0u) is unclear
typename _Integral = _Requires<is_integral<_Tp>>,
typename _Promoted = typename common_type<int, _Tp>::type>
static_assert(__or_<is_signed<_Tp>, is_same<int, _Promoted>>::value,
"integral arguments to abs must be signed or promotable to int");
return __x < 0 ? -__x : __x;
This works for abs((short)0) and abs(unsigned short)0) and
abs((__int128)0), but fails for abs(0u) and abs(0ul).
I guess we also want abs((__float128)0) to work, without casting it to
double, which would lose precision for large values. That fails today,
and would still fail with the function template above, but we can add
an overload for __float128.
Is not supporting the __intN types in C++03 mode OK?
More information about the Libstdc++