19

Is there any possibility to force a template to be from a certain base class so that I can call the base class function?

template <class T>
void SomeManager::Add(T)
{
    T->CallTsBaseClassFunction();
    //... do other stuff
}
Milan
  • 1,743
  • 2
  • 13
  • 36
cppanda
  • 1,235
  • 1
  • 15
  • 29
  • Possible duplicate of [Template Constraints C++](http://stackoverflow.com/questions/122316/template-constraints-c). – Frédéric Hamidi Feb 13 '11 at 14:07
  • 1
    Why don't you just call the function and see if it works? – Bo Persson Feb 13 '11 at 14:21
  • 3
    @Bo Persson: because that only guarantees nominal, not structural inheritance. You might end up calling `Random::CallTsBaseClassFunction` if `class Random` just happens to implement a function by the same name. – MSalters Feb 14 '11 at 10:34

3 Answers3

25

Sure, you can combine type traits with SFINAE:

#include <type_traits>

template <class T>
typename std::enable_if<std::is_base_of<your_base_class, T>::value, void>::type
SomeManager::Add(T)
{
    T->CallTsBaseClassFunction();
    //... do other stuff
}

Although I don't really see the benefit here.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • The benefit is that you can force the users of your class to inherit some base class, which contains some abstract function. – Yves Jul 21 '20 at 03:50
  • 1
    @Yves But if it's a template then what's the advantage of virtualization? You already get static dispatch. – user975989 Jul 21 '20 at 07:43
  • 1
    @user975989 No, what I meant is, for example, you develop a template class, which is to process data with different type: `void handle(T t) { this.processData(t.getValue());}`. Other people can develop different data, such as `class DataTypeA`, `class DataTypeB`. Now, you must force the writer of `DataTypeA` and `DataTypeB` to write the member function `getValue()`. To do so, you can write an abstract class, containing an abstract function `getValue()`. If `DataTypeA` didn't inherit the abstract class, generate an ERROR. – Yves Jul 21 '20 at 07:54
  • @Yves Sure, but if you just call the function template and `DataTypeA` doesn't have `getValue()`, it would still error. – user975989 Jul 24 '20 at 21:34
  • @user975989 This is exactly what we need: if `DataTypeA` doesn't contain a method named `getValue()`, it would generate an error. – Yves Jul 25 '20 at 01:01
  • 1
    @Yves that's what I mean. You don't need an abstract base class. – user975989 Jul 25 '20 at 01:54
  • @user975989 This is the same conversation that happened in the comments of the question. See MSalters response for why this is not the same thing. – Matthew M. Mar 03 '22 at 17:34
10

Worth to mention that it can be done at compile time in a more readable fashion with static_assert. Something in the lines of:

class Base {};

template<class B>
class Template{
    static_assert(std::is_base_of<Base, B>::value, "B must derive from nmspc::Base");
}

It works even when B is exactly Base. If Base is itself a templated class it becomes more complicated but it can still be done and there's plenty of resources online.

NicoBerrogorry
  • 446
  • 4
  • 15
9

The easiest solution is to add a snippet of code that compiles only if it's what you expected:

template <class T>
void SomeManager::Add(T t)
{
    assert((Base const*)&t); // T must inherit from Base to allow T*->Base* conversion.
    t.CallTsBaseClassFunction();
    //... do other stuff
}
MSalters
  • 173,980
  • 10
  • 155
  • 350