I've been trying to write a type trait that tells if a type T is implicitly default-constructible. Examples of implicitly/explicitly default-constructible types:
struct Imp { Imp() = default; };
struct Exp { explicit Exp() = default; };
Imp i1{};
Imp i2 = {}; // ok
Exp e1{};
Exp e2 = {}; // error
The type trait I tried looks like this:
#include <type_traits>
template<typename T>
struct IsImplicitlyDefaultConstructible {
private:
template<typename U> static void helper(const U&);
template<typename U> static std::true_type test(decltype(helper<U>({}))*);
template<typename U> static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
struct Yes { Yes() = default; };
struct No { explicit No() = default; };
int main()
{
static_assert(IsImplicitlyDefaultConstructible<Yes>::value, "");
static_assert(!IsImplicitlyDefaultConstructible<No>::value, "");
}
The idea is to test whether {} is convertible to const T&. Strangely, the code above works on GCC 6.1+, but fails on GCC 4/5 and all versions of Clang. See demo here.
So what is happening? Is this a bug in GCC 6.1+, or in the other versions? How can I make this trait work (preferably with C++11, but okay if C++14 is required)?
Aucun commentaire:
Enregistrer un commentaire