开发者

Designing hiearchical classes with template function

开发者 https://www.devze.com 2023-04-11 04:21 出处:网络
I am writing a class Base which has a member function taking a template parameter: class Base { template<class T>

I am writing a class Base which has a member function taking a template parameter:

class Base {
  template<class T>
  void func(const T&a开发者_如何学Gomp; t) { ... }
};

There's a class Derived which conceptually inherits natures of Base and has the same function func with different implementation.

At first I thought of deriving Derived from Base and make func virtual, but I can't because it's template.

I also thought of CRTP, but it's an option because instances must be able to put into a container and be accessible without knowing exact types of them:

std::vector<Base*> v = ...;
v[0]->func(...);
v[1]->func(...);

Overloading for possible types of T is also not an option.

What is the best solution to this situation?

And aside from the topic, would you recommend references (preferably books) for such kind of problems?


You cannot mix compile time polymorphism (templates) with runtime polymorphism like that. The problem is that with a template, the compiler will generate the code on-demand when it is used, and in your particular case, you want to decide what member function to instantiate based on the runtime type of the object in the vector.

If the number of types that can be used with the methods is limited, you can provide different virtual overloads, if you don't want to do that manually, you can probably define a type list with all of the types T, and then use that typelist to generate the methods... but that will be awful to code and maintain.

I recommend that you state the actual requirements of the problem (rather than the requirements of your proposed solution), and people will be able to provide alternative approaches.


This is not something easily done with C++. It's related to something called "first class polymorphism", which means it would be easy if the values in C++ could have polymorphic types. This is not the case.

If you'll be fine with a generic solution (that means the code f must be the same for all T), you can maybe do it, but it will be a laborious task.

Basically, you'll want to replace your const T &t parameter with a parameter whose type that wouldn't be generic, but will capture "inside" all the behaviour f needs from ts of all possible types.

For an example, let's say T is meant to be a functor, that f calls with an int argument. In this case, you'll change the declaration to

  virtual void func(const std::function<void(int)>& t) { ... }

and virtual functions will start to work. However, that means the interface of Ts will have to be fixed before you start to implement it in derived classes (meaning if you change your mind and want to call t with an argument of type ostream, you're out of luck).

However, creating such polymorphic wrappers ranges from easy (as is boost::any, boost::function) to hard or even impossible (any_iterator). It's very dependent on what you want to do.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号