A trait that test if one type is implicitly convertible to another type without narrowing.
Tested on MSVC 19.29 with /std:c++20
, GCC 11.2 with -std=c++20
, clang 12 (clang-cl) with /std:c++latest
.
This gist is released under GLWTPL.
2021/12/21 update:
- implement P1957R2, which considers pointer-to-bool conversion as narrowing.
- add
is_nothrow_non_narrowing_convertible
which detects non-throwing-ness besides non-narrowing-ness.
template <typename From, typename To>
struct is_non_narrowing_convertible;
template<typename From, typename To>
struct is_nothrow_non_narrowing_convertible;
1) If the imaginary function definition To test() { return { std::declval<From>() }; }
is well-formed, (that is, either std::declval<From>()
can be converted to To
using implicit conversions without narrowing, or both From
and To
are possibly cv-qualified void), provides the member constant value equal to true
. Otherwise value is false
. For the purposes of this check, the use of std::declval
in the return statement is not considered an odr-use.
Access checks are performed as if from a context unrelated to either type. Only the validity of the immediate context of the expression in the return statement (including conversions to the return type) is considered.
2) Same as 1), but the conversion is also noexcept.
From
and To
shall each be a complete type, (possibly cv-qualified) void
, or an array of unknown bound. Otherwise, the behavior is undefined.
If an instantiation of a template above depends, directly or indirectly, on an incomplete type, and that instantiation could yield a different result if that type were hypothetically completed, the behavior is undefined.
The behavior of a program that adds specializations for any of the templates described on this page is undefined.
template <typename From, typename To>
inline constexpr bool is_non_narrowing_convertible_v = is_non_narrowing_convertible<From, To>::value;
template <typename From, typename To>
inline constexpr bool is_nothrow_non_narrowing_convertible_v = is_nothrow_non_narrowing_convertible<From, To>::value;