PrevUpHomeNext

Type relationship safely_constructible

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.

Valid Expressions

expression

value

T, U

any types

safely_constructible<T, U>::value

true if a variant for which T is one of the value types should be constructible from U.

Notes

Examples

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] Note

You may specialize safely_constructible as you please in order to modify the behavior of strict_variant.

Definition

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 {};

PrevUpHomeNext