The safely_constructible
type trait is a refinement of std::is_constructible
,
which has special behavior for fundamental types and pointer types and forbids
certain conversions.
expression |
value |
---|---|
|
any types |
|
|
T
, U
if they are an arithmetic type or
a pointer type, after decay
.
safe_arithmetic_conversion
.
safe_pointer_conversion
.
static_assert(safely_constructible<unsigned char, char>::value, ""); static_assert(!safely_constructible<char, unsigned char>::value, ""); static_assert(safely_constructible<unsigned int, int>::value, ""); static_assert(!safely_constructible<int, char>::value, ""); static_assert(!safely_constructible<int, bool>::value, ""); static_assert(!safely_constructible<char, bool>::value, ""); static_assert(safely_constructible<double, float>::value, ""); static_assert(!safely_constructible<float, double>::value, ""); static_assert(!safely_constructible<int, double>::value, ""); static_assert(!safely_constructible<double, int>::value, ""); static_assert(!safely_constructible<bool, const char *>::value, ""); static_assert(!safely_constructible<const void *, const char *>::value, ""); static_assert(safely_constructible<const char *, char *>::value, ""); static_assert(!safely_constructible<char *, const char *>::value, ""); static_assert(safely_constructible<const char *, decltype("foo")>::value, ""); static_assert(!safely_constructible<char *, decltype("foo")>::value, ""); static_assert(safely_constructible<std::string, const char *>::value, ""); static_assert(safely_constructible<std::string, decltype("foo")>::value, ""); static_assert(!safely_constructible<const char *, std::string>::value, "");
Note | |
---|---|
You may specialize |
The complete definition of the safely_constructible
template is given:
// Helper metafunction which checks if type is arithmetic after decay. // This is the same as, `is_arithmetic` modulo `const` and references. template <typename T> struct decay_to_arithmetic : std::is_arithmetic<mpl::decay_t<T>> {}; // Helper metafunction which checks if type is pointer after decay template <typename T> struct decay_to_ptr : std::is_pointer<mpl::decay_t<T>> {}; // Primary template, falls back to std::is_constructible template <typename A, typename B, typename ENABLE = void> struct safely_constructible : std::is_constructible<A, B> {}; // If both are arithmetic after decay, then pass to safe_arithmetic_conversion template <typename A, typename B> struct safely_constructible<A, B, mpl::enable_if_t<decay_to_arithmetic<A>::value && decay_to_arithmetic<B>::value>> : safe_arithmetic_conversion<mpl::decay_t<A>, mpl::decay_t<B>> {}; // If both are pointer after decay, then pass to safe_pointer_conversion template <typename A, typename B> struct safely_constructible<A, B, mpl::enable_if_t<decay_to_ptr<A>::value && decay_to_ptr<B>::value>> : safe_pointer_conversion<mpl::decay_t<A>, mpl::decay_t<B>> {}; // If one is arithmetic and the other is pointer, after decay, it is forbidden. template <typename A, typename B> struct safely_constructible<A, B, mpl::enable_if_t<(decay_to_arithmetic<A>::value && decay_to_ptr<B>::value) || (decay_to_ptr<A>::value && decay_to_arithmetic<B>::value)>> : std::false_type {};