Type relationship safe_arithmetic_conversion (original) (raw)
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.
Valid Expressions
| expression | value |
|---|---|
| T, U | any arithmetic types |
| safe_arithmetic_conversion<T, U>::value | true if a variant for which T is one of the value types should be constructible from U. |
Notes
- Conversions between any two arithmetic categories are considered unsafe.
- If a conversion could be narrowing on some conforming implementation of C++, then it is not safe. (So,
long longcannot be converted tolongandlongcannot be converted toint, 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. - Signed can be converted to unsigned, but the reverse is not allowed (since it is typically implementation-defined, and may trigger warnings).
Definition
The complete definition is given:
template <typename A, typename B> struct safe_arithmetic_conversion { static constexpr bool same_class = (mpl::classify_arithmetic::value == mpl::classify_arithmetic::value); static constexpr bool unsign_to_sign = !std::is_unsigned::value && std::is_unsigned::value; static constexpr bool narrowing = (mpl::arithmetic_rank::value < mpl::arithmetic_rank::value);
static constexpr bool value = same_class && !unsign_to_sign && !narrowing; };
template 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 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 involvingchar 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 strict_variant, but it might not always be the simplest way. Consider specializing arithmetic_rank and/or classify_arithmetic, or safely_constructible, instead. |
![[Note]](https://cbeck88.github.io/strict-variant/images/note.png)