Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::is_default_constructible<T> error, if constructor is private

I have following snippet

#include <type_traits>
#include <boost/type_traits.hpp>

class C { C() { } };

int main()
{
   static_assert(!boost::has_trivial_default_constructor<C>::value, "Constructible");
   static_assert(!std::is_default_constructible<C>::value, "Constructible");
}

Conditions are not equal, but first condition works fine and second construction give error, that constructor is private. Compiler gcc 4.7... So, is this gcc bug, or it's defined by standard?

http://liveworkspace.org/code/NDQyMD$5

OK. Since this conditions are really unequal - we can use something like this

#include <type_traits>
#include <boost/type_traits.hpp>

class C { private: C() noexcept(false) { } };

int main()
{
   static_assert(!boost::has_nothrow_constructor<C>::value, "Constructible");
   static_assert(!std::is_nothrow_constructible<C>::value, "Constructible");
}

http://liveworkspace.org/code/NDQyMD$24

Anyway, i know, that static_assert should not fails, since types are really not default constructible/not nothrow constructible. Question is: WHY there is compilation error, not by my static assert?

like image 500
ForEveR Avatar asked Dec 25 '12 11:12

ForEveR


1 Answers

Looks like a compiler bug. Let's see the following example of SFINAE(similar implementation is used in g++'s type_traits header)

#include <type_traits>

class Private
{
    Private()
    {

    }
};

class Delete
{
    Delete() = delete;
};

struct is_default_constructible_impl
{
    template<typename T, typename = decltype(T())>
    static std::true_type test(int);

    template<typename>
    static std::false_type test(...);
};

template <class T>
struct is_default_constructible: decltype(is_default_constructible_impl::test<T>(0))
{

};

int main()
{
    static_assert(is_default_constructible<Private>::value, "Private is not constructible");
    static_assert(is_default_constructible<Delete>::value, "Delete is not constructible");
}

The second assert works as expected, we can't deduce Delete type, since the class has only one deleted constructor. But when compiler tries to deduce type of Private(), it gives error: Private::Private() is private. So, we have two classes with private constructor, but one of them gives error, and second - not. I think, that this behavior is wrong, but I can't find confirmation in the standard.

P.S. all off presented codes compiles by clang without any errors.

like image 102
awesoon Avatar answered Nov 17 '22 15:11

awesoon