The safe_arithmetic_conversion
type trait has the same syntax as std::is_constructible
.
It determines the behavior of safely_constructible
for arithmetic types.
It is defined in terms of sign, arithmetic category and arithmetic rank of its arguments.
expression |
value |
---|---|
|
any arithmetic types |
|
|
long
long
cannot be converted to long
and long
cannot be converted to int
,
even if you are on a 32-bit machine and they have the same size for you,
because it could be narrowing on a 64-bit machine.) This is determined
by checking if the arithmetic
rank decreases as a result of the conversion.
The complete definition is given:
template <typename A, typename B> struct safe_arithmetic_conversion { static constexpr bool same_class = (mpl::classify_arithmetic<A>::value == mpl::classify_arithmetic<B>::value); static constexpr bool unsign_to_sign = !std::is_unsigned<A>::value && std::is_unsigned<B>::value; static constexpr bool narrowing = (mpl::arithmetic_rank<A>::value < mpl::arithmetic_rank<B>::value); static constexpr bool value = same_class && !unsign_to_sign && !narrowing; }; template <typename A> struct safe_arithmetic_conversion<A, char> { static constexpr bool value = safe_arithmetic_conversion<A, signed char>::value && safe_arithmetic_conversion<A, unsigned char>::value; }; template <typename B> struct safe_arithmetic_conversion<char, B> { static constexpr bool value = safe_arithmetic_conversion<signed char, B>::value && safe_arithmetic_conversion<unsigned char, B>::value; }; template <> struct safe_arithmetic_conversion<char, char> : std::true_type {};
The type char
requires special
treatment, because it is implementation-defined if it is signed
or unsigned
. Since we'd like
to eliminate implementation-specific behavior, an arithmetic conversion involving
char
is permitted only when
it would be permitted for both signed
char
and unsigned
char
.
Note | |
---|---|
You are welcome to specialize this trait to modify the behavior of |