Search code examples
c++templates

Restrict C++ Template Parameter to Subclass


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();

}

Solution

  • Starting with C++20, you can constrain template arguments. One way to do that is the requires clause. You can use it as follows in your case (i.e. to ensure T is a subclass of a specific class Baseclass):

    template <class T> void function()
       requires( std::is_base_of_v<Baseclass,T> )
    {
       T *object = new T();
    }
    

    Alternatively, for frequently used constraints, you can use named concepts, which allow for a more succinct syntax (credit to @sklott):

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

    Using constraints is better than using a static_assert, because they'll allow you to have multiple implementations of function with different constraints. For example, you can have another implementation for when T derives from a different class. If desired, you can also have a default implementation that doesn't specify any constraints at all, to be picked by the compiler when none of the constrained implementations qualify. None of these would be possible using static_assert.

    PS. The requires clause is great for ad hoc constraints, and named concepts are great for frequently used constraints (you can also create your own named concepts using the concept keyword). You can read more about constraints and alternative ways to apply them here, about std::is_base_of_v here, and about std::derived_from here. For more advanced use cases, also be sure to read about requires expressions, which are not to be confused with the requires clause, even though they share the same requires keyword.