Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a tricky way to avoid overriding all pure virtual functions of template base class, used in multiple inheritance

Pretty complicated (and bad) title, here's what I mean by example:

struct type1 {};
struct type2 {};
struct type3 {};

template< typename TYPE >
struct interface {
    virtual void f( TYPE ) = 0;
};

struct processor {
    template< typename TYPE >
    void f( TYPE ) {
        // something + for some TYPE-s have specializations, but it's irrelevant
    }
};

struct der: interface< type1 >, interface< type2 >, interface< type3 > {
    processor p;

    void f( type1 t ){ p.f( t ); }
    void f( type2 t ){ p.f( t ); }
    void f( type3 t ){ p.f( t ); }
};

Is there any tricky way to avoid all overrides in der? In the real case, der inherits interface 10 times (with different template types and it could be extended in the future). And it's rather ugly to have 10+ overrides of f when their bodies are the same.

processor could be changed to anything, also der::p could be some container, holding a template-d processor, etc.

It sounds like I want to have a virtual template member function f, which is not allowed.

I thought about using a macro, but I don't like that idea.

EDIT Note: can't use c++11, unfortunately. And can't change typeN types, which are not in hierarchy.

like image 440
Kiril Kirov Avatar asked Oct 22 '25 22:10

Kiril Kirov


2 Answers

C++03 solutions

(See KerrekSB's answer for solutions using C++11 features)

You can use another layer of inheritance and CRTP to dispatch the calls to your processor:

template< typename TYPE, class ProcessorHolder >
struct processorDispatch : interface<TYPE> {
    virtual void f( TYPE t ) override {
        processor& p = static_cast<ProcessorHolder*>(this)->p; //CRTP --> explicit downcast
        p.f(t);
    }
};

And use it as

struct der: processorDispatch< type1,der >, processorDispatch< type2,der >, processorDispatch< type3,der > {
    processor p;

  //make f visible - either
    using processorDispatch< type1,der >::f;
    using processorDispatch< type2,der >::f;
    using processorDispatch< type3,der >::f;
  //or
    template <typename TYPE>
    void f(TYPE t) {
      processorDispatch<TYPE, der>::f(t);
    }
}

};

A take at Kerrek's non-CRTP-solution, but "C++11-free" vía base class chaining:

struct der_base {
  processor p;
};

template <class TYPE, class Base = der_base>
struct der_t : Base, interface<TYPE> {
  void f(TYPE t) { this->p.f(t); } 
  using Base::f;
};

template <class TYPE>
struct der_t<TYPE, der_base> : der_base, interface<TYPE> {
  void f(TYPE t) { this->p.f(t); } 
};

And then use

typedef der_t<type1, der_t<type2, der_t<type3> > > der;
like image 94
Arne Mertz Avatar answered Oct 25 '25 13:10

Arne Mertz


You could make der a template:

template <typename ...> struct der;

template <> struct der<>
{
    processor p;
};

template <typename Base, typename ...Rest>
struct der<Base, Rest...> : der<Rest...>, interface<Base> 
{ 
    void f(Base x) { this->p.f(x); }
};

Then use:

der<type1, type2, type3> d;

Here's an alternative design using CRTP:

template <typename Actual, typename Base> struct FImpl : Base
{
    void f(Base x) { static_cast<Actual*>(this)->p.f(x); }
};

template <typename ...T> struct der : FImpl<der, T>...
{
    processor p;
};
like image 45
Kerrek SB Avatar answered Oct 25 '25 13:10

Kerrek SB



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!