1

I was following template class restriction, but ran into errors in gcc:

error: multiple types in one declaration

error: declaration does not declare anything

It compiles if I remove the enable_if block. Can anybody explain if I am missing something?

template<class A, class B, class C, class D>                                                                               
typename std::enable_if<                                                  
std::is_base_of<baseofA, A>::value &&                      
std::is_base_of<baseofB, B>::value &&      
std::is_base_of<baseofC, C>::value &&            
std::is_base_of<baseofD, D>::value>::type       
class library {
    //whatever
};
Community
  • 1
  • 1
user1394884
  • 211
  • 1
  • 2
  • 6
  • Are you trying to have special behavior selected based on A,B,C and D or do you just want a compile time error if the condition fails? –  Jun 12 '12 at 02:51
  • I just want an error if the condition fails. – user1394884 Jun 12 '12 at 02:53
  • 1
    Then static_assert or (boost's static assert( http://www.boost.org/doc/libs/1_49_0/doc/html/boost_staticassert.html)) is the correct tool for this problem. enable_if is mainly usesul to switch functions at compile time(for example see if you can memcpy a class instead of copy construct it). –  Jun 12 '12 at 03:09

2 Answers2

3

You're not using enable_if correctly. static_assert would be more appropriate in this case.

template<class A, class B, class C, class D>       
class library {
  static_assert(
    std::is_base_of<baseofA, A>::value &&                      
    std::is_base_of<baseofB, B>::value &&      
    std::is_base_of<baseofC, C>::value &&            
    std::is_base_of<baseofD, D>::value, 
    "template argument A must derive from baseofA and so on ..." );
      //whatever
};

If you want to use enable_if instead you must create a dummy template parameter that depends on the enabled type for it to work as you desire.

template<class A, 
         class B, 
         class C, 
         class D, 
         class _ = 
           typename std::enable_if<                                                  
             std::is_base_of<baseofA, A>::value &&                      
             std::is_base_of<baseofB, B>::value &&      
             std::is_base_of<baseofC, C>::value &&            
             std::is_base_of<baseofD, D>::value>
           ::type>
class library {
    //whatever
};

But IMO, the static_assert method is better because you can provide a descriptive error message instead of the compiler complaining about failing to find a type named type in the latter case.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
0

Following this page, try

template<class A, class B, class C, class D, class Enable = void>
class library;

template<class A, class B, class C, class D>                                                                      
class library<A, B, C, D, typename std::enable_if< std::is_base_of<baseofA, A>::value &&
                                                   std::is_base_of<baseofB, B>::value &&
                                                   std::is_base_of<baseofC, C>::value &&
                                                   std::is_base_of<baseofD, D>::value >::type
             >
{
    //whatever
};

Note that there must be something wrong with your example, since enable_if<>::type is a type, which you wouldn't want between the template<> line and the class library line.

David Norman
  • 19,396
  • 12
  • 64
  • 54