2016-07-04 2 views

ответ

8

От 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, что дает truevalue.

Если специализация не может быть создана (т. Е. T(std::declval<Args>()...) недействительна), компилятор возвращается к общему шаблону, который всегда может быть создан. Этот наследует от std::false_type, что дает falsevalue.

Live on Coliru

Более точные черты, такие как std::is_trivially_constructible, необходимо более продвинутое знание правил языка, чтобы обработать выражение, справедливость должна стать значением признака. Если это окажется неосуществимым изнутри языка, например, с std::is_standard_layout, тогда сам компилятор должен предоставить внутреннюю функцию для получения значения.

+0

Это было отличное объяснение, спасибо! – Alex

+0

Это не совсем эквивалентно 'std :: is_constructible', потому что' T (Arg) 'эквивалентно C-style cast, поэтому ваш' is_constructible 'is' true', а ' std' one вернет false. –