http://stackoverflow.com/questions/2733377/is-there-a-way-to-test-whether-a-c-class-has-a-default-constructor-other-than
Works on gcc-4.6
#include <type_traits>
template< class T >
struct identity {
typedef T type;
};
template<bool, typename T, typename F>
struct if_c : identity<F> {};
template< typename T, typename F>
struct if_c<true,T,F> : identity<T> {};
template<typename Bool, typename T, typename F>
struct if_ : if_c< Bool::value, T, F> {};
template< class T >
struct is_default_constructible_;
template< class T >
struct is_default_constructible :
if_< std::is_arithmetic<T>,
std::true_type,
is_default_constructible_<T> >::type { };
template< class T >
struct is_default_constructible_ {
template<class D> class Acessible : public D
{
friend class is_default_constructible_<D>;
public:
//using D::D; may be needed once N2540 is implemented
};
template<int x>
class receive_size{};
template< class U >
static int sfinae( receive_size< sizeof Acessible<U>() > * );
template< class U >
static char sfinae( ... );
public:
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
};
struct p { p(); };
class q { q(); };
class r { r(int); };
#include <iostream>
using namespace std;
int main() {
cerr << is_default_constructible<int>::value << endl // outputs 1
<< is_default_constructible<p>::value << endl
<< is_default_constructible<q>::value << endl
<< is_default_constructible<r>::value << endl; // outputs 0
}
template< class T >
class is_default_constructible {
template<int x>
class receive_size{};
template< class U >
static int sfinae( receive_size< sizeof U() > * );
template< class U >
static char sfinae( ... );
public:
enum { value = sizeof( sfinae<T>(0) ) == sizeof(int) };
};
class q { q(); };
class r { r(int); };
#include <iostream>
using namespace std;
int main() {
cerr << is_default_constructible<int>::value << endl // outputs 1
// fails to compile: access violation
// FCD demands that access violations be unrecoverable
// indeed, it's murky: q is default-constructible, but only "rarely"
//<< is_default_constructible<q>::value << endl
<< is_default_constructible<r>::value << endl; // outputs 0
}
namespace std {
namespace detail {
template<typename _B1, typename _B2>
struct __and_
: public conditional<_B1::value, _B2, _B1>::type
{ };
template<typename _Pp>
struct __not_
: public integral_constant<bool, !_Pp::value>
{ };
template<typename _Tp>
struct __is_array_known_bounds
: public integral_constant<bool, (extent<_Tp>::value > 0)>
{ };
template<typename _Tp>
struct __is_array_unknown_bounds
: public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
{ };
struct __do_is_default_constructible_impl
{
template<typename _Tp>
static true_type __test(int,decltype(_Tp())* a = 0);
template<typename>
static false_type __test(...);
};
template<typename _Tp>
struct __is_default_constructible_impl
: public __do_is_default_constructible_impl
{
typedef decltype(__test<_Tp>(0)) type;
};
template<typename _Tp>
struct __is_default_constructible_atom
: public __and_<__not_<is_void<_Tp>>,
__is_default_constructible_impl<_Tp>>::type
{ };
template<typename _Tp, bool = is_array<_Tp>::value>
struct __is_default_constructible_safe;
// The following technique is a workaround for a current core language
// restriction, which does not allow for array types to occur in
// functional casts of the form T(). Complete arrays can be default-
// constructed, if the element type is default-constructible, but
// arrays with unknown bounds are not.
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>,
__is_default_constructible_atom<typename
remove_all_extents<_Tp>::type>>::type
{ };
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, false>
: public __is_default_constructible_atom<_Tp>::type
{ };
} // namespace detail
/// is_default_constructible
template<typename _Tp>
struct is_default_constructible
: public integral_constant<bool, (detail::__is_default_constructible_safe<
_Tp>::value)>
{ };
}
template<class T = void> struct is_default_constructible;
template<> struct is_default_constructible<void>
{
protected:
// Put base typedefs here to avoid pollution
struct twoc { char a, b; };
template<bool> struct test { typedef char type; };
public:
static bool const value = false;
};
template<> struct is_default_constructible<>::test<true> { typedef twoc type; };
template<class T> struct is_default_constructible : is_default_constructible<>
{
private:
template<class U> static typename test<!!sizeof(::new U())>::type sfinae(U*);
template<class U> static char sfinae(...);
public:
static bool const value = sizeof(sfinae<T>(0)) > 1;
};