Явная фигура

Как я могу проверить, является ли конкретный тип typename T конструктивным из аргументов typename ...Args способом T{Args...} ? Я знаю std::is_constructible из , но он работает с круглыми скобками, а не с фигурными фигурными скобками. У меня нет слишком большого опыта написания черт типа, поэтому я не могу представить пример. В качестве упрощения мы можем принять любые разумные утверждения, даже если это приводит к не слишком значительной потере общности.

 template decltype(void(T{std::declval()...}), std::true_type()) test(int); template std::false_type test(...); template struct is_braces_constructible : decltype(test(0)) { }; 

Решение для моего classа SFINAE:

 #include  template< typename ...types > struct identity { }; template< typename ...types > struct void_t { using type = void; }; template< typename type, typename identity, typename = void > struct is_embraceable : std::false_type { }; template< typename type, typename ...arguments > struct is_embraceable< type, identity< arguments... >, void_t< decltype(type{std::declval< arguments >()...}) > > : std::true_type { }; template< typename type, typename ...arguments > constexpr bool is_embraceable_v = is_embraceable< type, identity< arguments... > >::value; 

C ++ позволяет также скопировать ссылки :

 struct dummy{}; dummy a; dummy & b{a}; dummy c{b}; dummy const& d{a}; dummy e{d}; 

Но is_braces_constructible из ответа Simple возвращает std::false_type для std::false_type инициализированных ссылок с GCC8, но работает, например, с ответом ORIGINAL от Clang 7. Orient не удается скомпилировать ссылки с привязкой к GCC8. Его EDITED-ответ даже возвращает std::false_type в гораздо большем числе случаев с GCC8 и Clang 7.

Вот ответ на C ++ 17, который (надеюсь) работает для всех случаев с GCC8:

 #include  #if __GNUC__ template< typename T, typename std::enable_if_t< std::is_lvalue_reference::value >* = nullptr > constexpr void gcc_workaround_braces_initialize_refs(T& t); template constexpr void gcc_workaround_braces_initialize_refs(T const& t); template< typename T, typename std::enable_if_t< !std::is_lvalue_reference::value >* = nullptr > constexpr T&& gcc_workaround_braces_initialize_refs(T&& t); template< typename T, typename Identity, typename = std::void_t<>> struct is_braces_constructible_impl : std::false_type {}; template< typename T, typename ...Args > struct is_braces_constructible_impl< T, std::tuple< Args... >, std::void_t< decltype(gcc_workaround_braces_initialize_refs({std::declval< Args >()...}))> > : std::true_type {}; #else // !__GNUC__ template< typename T, typename Identity, typename = std::void_t<>> struct is_braces_constructible_impl : std::false_type {}; template< typename T, typename ...Args > struct is_braces_constructible_impl< T, std::tuple< Args... >, std::void_t< decltype(T{std::declval< Args >()...}) > > : std::true_type {}; #endif // !__GNUC__ template struct is_braces_constructible { using type = is_braces_constructible_impl< T, std::tuple< Args... > >; static inline constexpr bool value = type::value; }; 

Живой код