tags:

views:

130

answers:

5

Hi How can I force a template parameter T to be a subclass of a specific class Baseclass? Something like this:

template <class T : Baseclass> void function(){
    T *object = new T();

}

Thanks in advance.

+8  A: 

In this case you can do:

template <class T> void function(){
    Baseclass *object = new T();

}

This will not compile if T is not a subclass of Baseclass (or T is Baseclass).

sepp2k
ah yes, that's a good idea. thanks!I take it then there's no way of defining it in the template definition?
phant0m
@phant0m: Correct. You can't explicitly constrain template parameters (except using concepts, which were considered for c++0x but then dropped). All constraints happen implicitly by the operations you perform on it (or in other words the only constraint is "The type must support all operations that are performed on it").
sepp2k
ah ic. Thanks a lot for the clarification!
phant0m
That executes the T() constructor, and requires the existence of the T() constructor. See my answer for a way that avoids those requirements.
Douglas Leeder
@Douglas: The call to the `T()` constructor is already in the original code. I only changed the type of the `object` variable, which doesn't introduce any additional requirement except the one we were after.
sepp2k
A: 

By calling functions inside your template that exist in the base class.

If you try and instantiate your template with a type that does not have access to this function, you will receive a compile-time error.

DanDan
This does not ensure that `T` *is a* `BaseClass` because the declared members in `BaseClass` could be repeated in the declaration of `T`.
Daniel Trebbien
+1  A: 

You could use Boost Concept Check's BOOST_CONCEPT_REQUIRES:

#include <boost/concept_check.hpp>
#include <boost/concept/requires.hpp>

template <class T>
BOOST_CONCEPT_REQUIRES(
    ((boost::Convertible<T, BaseClass>)),
(void)) function()
{
    //...
}
Daniel Trebbien
thanks for the suggestion. I will check it out.
phant0m
+1  A: 

You don't need concepts, but you can use SFINAE:

template <typename T>
boost::enable_if< boost::is_base_of<Base,T>::value >::type function() {
   // This function will only be considered by the compiler if
   // T actualy derived from Base
}

Note that this will instantiate the function only when the condition is met, but it will not provide a sensible error if the condition is not met.

David Rodríguez - dribeas
What if you wrap all functions like this? btw what does it return?
the_drow
The `enable_if` takes a second type parameter that defaults to `void`. The expression `enable_if< true, int >::type` represents the type `int`. I cannot really understand what your first question is, you can use SFINAE for whatever you wish, but I don't quite understand what you intend to do with this over all functions.
David Rodríguez - dribeas
+1  A: 

To execute less useless code at runtime you can look at: http://www2.research.att.com/~bs/bs_faq2.html#constraints which provides some classes that perform the compile time test efficiently, and produce nicer error messages.

In particular:

template<class T, class B> struct Derived_from {
        static void constraints(T* p) { B* pb = p; }
        Derived_from() { void(*p)(T*) = constraints; }
};

template<class T> void function() {
    Derived_from<T,Baseclass>();
}
Douglas Leeder
thanks for the link!
phant0m