5

I am writing a template class and want to find out whether template argument is default constructible is there any way to do it ?

The code is something like following

template <class C>
class A
{

createObj()
{
C* objPtr = NULL;
// If default constructible then create object else let it remain NULL
}
};

Update: I have tried using code given in this question but it doesn't work, to be precise if return default constructible even for those classes which aren't, I have no idea why is that happening.

Community
  • 1
  • 1
Gaurav
  • 794
  • 2
  • 11
  • 32

2 Answers2

3

This is a classical case for SFINAE and enable_if.

In another answer, Potatoswatter has already posted a type trait is_default_constructible that can be reused here:

void createObj(
    typename enable_if_c<is_default_constructible<C>::value, void>::type* dummy = 0)
{
     C* objPtr = new C();
}

void createObj(
    typename disable_if_c<is_default_constructible<C>::value, void>::type* dummy = 0)
{
     C* objPtr = 0;
}

Or, if your function has a non-void return type T (thanks to DeadMG) you can omit the dummy default argument:

typename enable_if_c<is_default_constructible<C>::value, T>::type createObj()
{
     C* objPtr = new C();
}

typename disable_if_c<is_default_constructible<C>::value, T>::type createObj()
{
     C* objPtr = 0;
}

SFINAE means that a template which cannot be instantiated for a given type, will not. enable_if_c basically results in a valid type if and only if its argument is true. Now we use the metafunction is_default_constructible to test whether the type C has a default constructor. If so, enable_if_c<…>::type will result in a valid type, otherwise it will not.

The C++ compiler will thus only see one of the two functions, to wit the one that is usable in your context. See the documentation of enable_if for more details.

Community
  • 1
  • 1
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Why not use enable_if on the return type and prevent the necessity of the dummy argument? Also, I believe you require a `typename` in there. – Puppy Jan 12 '11 at 13:14
  • @DeadMG: because this only works for non-`void`. The OP hasn’t specified a return type … – Konrad Rudolph Jan 12 '11 at 13:15
  • @Konrad I didn't get the code, can you write in detail, also I can't use boost. Thanks – Gaurav Jan 12 '11 at 13:16
  • @Gaurav: if you cannot use Boost, just copy the header of the `enable_if` template. – Konrad Rudolph Jan 12 '11 at 13:20
  • @Konrad I tried to use is_default_constructible but it is not working. Specifically I am getting def const even for classes which aren't Any idea what might be the problem :-(. Thanks. – Gaurav Jan 12 '11 at 13:26
  • @Gaurav: sorry … :-( Apparently this requires compiler support that is only available in very few compilers, see [Boost.TypeTraits: `has_trivial_constructor`](http://www.boost.org/doc/libs/1_42_0/libs/type_traits/doc/html/boost_typetraits/reference/has_trivial_constructor.html). There doesn’t seem to be a good solution then. – Konrad Rudolph Jan 12 '11 at 13:28
  • has_trivial_constructor is not the same as this though. We want to know if there is an accessible default constructor and not whether it is trivial. – CashCow Jan 12 '11 at 13:54
  • Does that code actually work? If they aren't template functions, then why won't it simply be a compile error? (something like missing type - defaulting to int) – doug65536 Dec 15 '12 at 22:08
  • @doug65536 They aren’t function templates but they are functions that depend on a template argument nevertheless (because they are member functions of a class template) so this will work. What you get is a template argument substitution failure and that is *not* an error (SFINAE). – Konrad Rudolph Dec 16 '12 at 13:14
  • So being a member of a template class already qualifies it for SFINAE to work? Does it work because it has another alternative that does work when the substitution failure is in error (and the overload is not considered) and vice versa when the bool condition is reversed? – doug65536 Dec 17 '12 at 08:05
  • @doug65536 Yes: SFINAE is used in the context of overload resolution. In the case of substitution failure in a function, that candidate function is simply removed from the set of possible overloads to consider. – Konrad Rudolph Dec 17 '12 at 08:17
  • I think you just nailed my issues with it! You always have to have another alternative that IS allowed. When the compiler has no alternative, it complains about the SFINAE overload, right? – doug65536 Dec 17 '12 at 08:21
  • @doug65536 Well if there’s no valid overload the compiler complains that it cannot find a function for the required call, like it would do if you would call an undeclared function. – Konrad Rudolph Dec 17 '12 at 09:43
1

This is a case of SFINAE, you use a function overload, one that takes ... as a parameter, one that calls the method you are looking for.

In any case this particular question is answered `here

Community
  • 1
  • 1
CashCow
  • 30,981
  • 5
  • 61
  • 92