Rationale for cmath's std::abs(short) -> double

Stephan Bergmann sbergman@redhat.com
Wed Feb 3 17:23:00 GMT 2016

On 02/03/2016 02:25 PM, Jonathan Wakely wrote:
> 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
>    template<typename _Tp,
>         typename _Integral = _Requires<is_integral<_Tp>>,
>         typename _Promoted = typename common_type<int, _Tp>::type>
>      constexpr _Promoted
>      abs(_Tp __x)
>      {
>        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;
>      }
> #endif
> 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?

Thanks for the detailed reply; LWG 2192 is what I had apparently 
forgotten about again.

(Personally, I'm probably even OK with the status quo---there's not too 
many cases where that issue hits in practice (at least not in 
LibreOffice), so sticking an explicit cast to int in isn't too much of a 
pain when one is aware of that shortcoming in the current standard.)

More information about the Libstdc++ mailing list