is-there-a-way-to-test-whether-a-c-class-has-a-default-constructor-other-than

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;
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值