Is-braces-constructible type trait

孤者浪人 提交于 2019-12-17 14:56:29

问题


How can I check whether specific type typename T is constructible from arguments typename ...Args in the manner T{Args...}? I aware of std::is_constructible< T, Args... > type trait from <type_traits>, but it works with parentheses, not curly braces. I do not have too much experience in writing of type traits, so I cannot provide initial example. As simplification we can accept any reasonable assertions, even if this leads to not too significant loss of generality.


回答1:


template<class T, typename... Args>
decltype(void(T{std::declval<Args>()...}), std::true_type())
test(int);

template<class T, typename... Args>
std::false_type
test(...);

template<class T, typename... Args>
struct is_braces_constructible : decltype(test<T, Args...>(0))
{
};



回答2:


My class-SFINAE-based solution:

#include <type_traits>


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;



回答3:


C++ allows to brace-initialize references, too:

struct dummy{};
dummy a;
dummy & b{a};
dummy c{b};

dummy const& d{a};
dummy e{d};

But is_braces_constructible from Simple's answer returns std::false_type for brace-initialized references with GCC8, but works e.g. with Clang 7. Orient's ORIGINAL answer fails to compile reference brace inits with GCC8, too. His EDITED answer even returns std::false_type in much more cases with both GCC8 and Clang 7.

Here is a C++17 answer that (hopefully) works for all cases with GCC8, too:

#include <type_traits>

#if __GNUC__

template<
    typename T,
    typename std::enable_if_t<
        std::is_lvalue_reference<T>::value
    >* = nullptr
>
constexpr void gcc_workaround_braces_initialize_refs(T& t);

template<typename T>
constexpr void gcc_workaround_braces_initialize_refs(T const& t);

template<
    typename T,
    typename std::enable_if_t<
        !std::is_lvalue_reference<T>::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<T>({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<class T, typename... Args>
struct is_braces_constructible {
    using type = is_braces_constructible_impl< T, std::tuple< Args... > >;
    static inline constexpr bool value = type::value;
};

Live Code



来源:https://stackoverflow.com/questions/20885541/is-braces-constructible-type-trait

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!