How to call a template method in a derived class that implements a pure virtual method in a base class?

I have a base class with a few clean virtual methods like

class GenericFunction { public: GenericFunction() { /* Init generic function state */ }; virtual void Iterate(short *ps, unsigned cs) = 0; virtual void Iterate(float *ps, unsigned cs) = 0; } 

Then I have a bunch of derived classes that implement certain functions, and I want to call the Iterate() method on the set of these functions, providing each of them with a block of data samples. I only know the data type the moment I call Iterate() .

The Iterate() methods Iterate() almost the same for many functions, so I would like to use a template. I cannot use the template in the base class because virtual templates are not allowed. To get the compiler to generate the correct methods from the template, I found that I need to use an indirect call to the template as follows:

 class SpecificFunction : GenericFunction { public: SpecificFunction() : GenericFunction() { /* Init specific function state */ }; template<class T> void IterateT(T *ps, unsigned cs) { // Do function operations on block of samples }; virtual void Iterate(short *ps, unsigned cs) { IterateT(ps, cs); }; virtual void Iterate(float *ps, unsigned cs) { IterateT(ps, cs); }; } 

I don’t want to do the whole class for the SpecificFunction template, because there are many other methods, and all this code does not depend on the type of samples used. I do not want all this code to be replicated when it was created from a template, because it works in the embedded processor and in the code space.

It seems confusing and ineffective. Is there a better way to do this?

+4
source share
1 answer

This is the case when a scary diamond (virtual inheritance and multiple inheritance) can help you. You can use the proxy class of the template, which inherits almost from your GenericFunction , to be your general implementation. Then use multiple inheritance for the specific implementations you want to create the SpecificFunction .

 class ProxyState; template <typename T> class ProxyFunction : public virtual GenericFunction { public: ProxyFunction() : GenericFunction() {}; virtual ProxyState * state () { return 0; } void Iterate (T *ps, unsigned cs) { // Do function operations on block of samples, using state() // if necessary std::cout << __PRETTY_FUNCTION__ << "\n"; } }; class SpecificFunction : public ProxyFunction<short>, public ProxyFunction<float> { public: SpecificFunction() : ProxyFunction<short>(), ProxyFunction<float>() { /* Init specific function state */ }; }; //... SpecificFunction s; GenericFunction *g = &s; g->Iterate((short *)0, 0); g->Iterate((float *)0, 0); 

The above program gives me the following result:

 void ProxyFunction<T>::Iterate(T*, unsigned int) [with T = short int] void ProxyFunction<T>::Iterate(T*, unsigned int) [with T = float] 

In graphical form, the diagram looks like this:

  GenericFunction | /_\ (virtual) | ProxyFunction<T> | ____________|____________ | | ProxyFunction<short> ProxyFunction<float> | | /_\ /_\ |_______ _______| | | SpecificFunction 

Since GenericFunction is practically inherited, SpecificFunction has only one instance, although it inherits several ProxyFunction<> s.

+1
source

Source: https://habr.com/ru/post/1493247/


All Articles