Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is std::is_constructible<T, Args> implemented? [duplicate]

So far I can't find anything ELI5 online. For a learning project I would like to implement my own is_constructible. Can someone explain how it works, please?

like image 556
Alex Avatar asked Jul 04 '16 09:07

Alex


1 Answers

From cppreference:

[I]f the variable definition T obj(std::declval<Args>()...); is well-formed, value is equal to true, else value is false.

Checking whether code is well-formed can be done with SFINAE techniques, for example the void_t<> trick (expected to be part of the C++1z standard library):

template <class...>
using void_t = void;

template <class, class T, class... Args>
struct is_constructible_ : std::false_type {};

template <class T, class... Args>
struct is_constructible_<
    void_t<decltype(T(std::declval<Args>()...))>,
T, Args...> : std::true_type {};

template <class T, class... Args>
using is_constructible = is_constructible_<void_t<>, T, Args...>;

The using hoop-hopping is there to place the void_t<> argument first. It usually comes last with a default type, but that position is held by the variadic Args pack.

When is_constructible_ is instantiated for <void, T, Args...>, the compiler tries to instantiate the specialization first. This only succeeds if the contents of void_t<...> are semantically valid, that is, T(std::declval<Args>()...) could be executed correctly -- as specified in the requirements of is_constructible. Note that I have used a temporary instead of a local variable, but to my knowledge the rules don't change between the two. The specialization inherits from std::true_type, which yields a true value.

If the specialization cannot be instantiated (i.e, T(std::declval<Args>()...) is not valid), the compiler falls back to the general template, which can always be instantiated. This one inherits from std::false_type, which yields the false value.

Live on Coliru

More precise traits, such as std::is_trivially_constructible, need more advanced knowledge of the language rules to craft the expression whose validity should become the value of the trait. If this proves infeasible from inside the language, such as with std::is_standard_layout, then the compiler itself has to provide an intrinsic function to retrieve the value.

like image 145
Quentin Avatar answered Oct 20 '22 00:10

Quentin