Пока что я не могу найти что-нибудь ELI5 онлайн. Для учебного проекта я хотел бы реализовать свой собственный is_constructible. Может кто-нибудь объяснить, как это работает, пожалуйста?Как реализуется std :: is_constructible <T, Args>?
ответ
От cppreference:
[I], F переменная определения
T obj(std::declval<Args>()...);
хорошо сформированы,value
равноtrue
, иначеvalue
являетсяfalse
.
Проверка ли код хорошо сформированным может быть сделано с методами SFINAE, к примеру void_t<>
трик (как ожидается, будет частью стандартной библиотеки С ++ 1Z):
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...>;
using
обруча -hopping, чтобы разместить аргумент void_t<>
. Обычно он заканчивается стандартным типом, но эта позиция удерживается в пакете Variadic Args
.
При создании объекта is_constructible_
за <void, T, Args...>
компилятор сначала пытается создать специализацию. Это выполняется только в том случае, если содержание void_t<...>
является семантически допустимым, то есть T(std::declval<Args>()...)
может быть выполнено правильно - как указано в требованиях is_constructible
. Обратите внимание, что я использовал временную вместо локальной переменной, но, насколько мне известно, правила не меняются между ними. Специализация наследуется от std::true_type
, что дает true
value
.
Если специализация не может быть создана (т. Е. T(std::declval<Args>()...)
недействительна), компилятор возвращается к общему шаблону, который всегда может быть создан. Этот наследует от std::false_type
, что дает false
value
.
Более точные черты, такие как std::is_trivially_constructible
, необходимо более продвинутое знание правил языка, чтобы обработать выражение, справедливость должна стать значением признака. Если это окажется неосуществимым изнутри языка, например, с std::is_standard_layout
, тогда сам компилятор должен предоставить внутреннюю функцию для получения значения.
Это было отличное объяснение, спасибо! – Alex
Это не совсем эквивалентно 'std :: is_constructible', потому что' T (Arg) 'эквивалентно C-style cast, поэтому ваш' is_constructible 'is' true', а ' std' one вернет false. –