C ++ mixins through templates: why doesn't this work?

I have an interface that is implemented as an abstract base class with many pure virtual public methods. These pure virtual functions can be implemented using a template, since the differences between the subclasses are small - so my idea was to use multiple inheritance to mix in an appropriate template helper class that provides the implementation. However, the compiler complains that the base class is abstract; he does not consider the implementation of auxiliary mixing; therefore, he does not see the implementation of the required method.

For instance:

class TrivialList {
    int count;
public:
    TrivialList(int count) : count(count){}
    virtual double Average() const=0;
    int Count() const {return count;}
    virtual ~TrivialList(){}
};
template<typename TIndexable> class AverageHelper {
public:
    double Average() const {
        TIndexable const & self = static_cast<TIndexable const &>(*this);
        double sum=0.0;
        for(int i=0;i<self.Count();++) sum += self.Get(i);
        return sum / self.Count();
    }
};
class IndexableList : public TrivialList, public AverageHelper<IndexableList> {
    std::vector<double> backend;
public:
    IndexableList(int count) : TrivialList(count), backend(count) { }
    double & Get(int i) { return backend[i];}
    double const & Get(int i) const { return backend[i];}
};
IndexableList * MakeList() {return new IndexableList(5);} //error!
//    cannot instantiate abstract class

I am using MSC 10.0 (Visual Studio 2010); the code does not work with a similar error using g ++ 4.5.

Get, , , (, /) - , .

+3
2

, AverageHelper<>::Average() TrivialList::Average(). , , .

:

template<typename TIndexable, typename Base > 
class AverageHelper : public Base {
public:
  template< typename T >
  AverageHelper(T arg) : Base(arg) {}
  // ... 
};

class IndexableList : public AverageHelper<IndexableList,TrivialList> {
public:
  IndexableList(int count) : AverageHelper<IndexableList,TrivialList>(count) {}
  // ...
};

TrivialList:

template<typename TIndexable, typename Base > 
class AverageHelper : virtual public Base {
  // ... 
};
+4

, , .

, , :

// ...
template<typename TIndexable> class AverageHelper : public TriviaList{

// ...
class IndexableList : public AverageHelper<IndexableList> {

, , , , , :

class Abstract {
public:
    virtual void foo() = 0;
    virtual void bar() = 0;
};

template<class Base>
class FooImpl : Base {
public:
    void foo() { /* default foo implementation */ }
};

template<class Base>
class BarImpl : Base {
public:
    void bar() { /* default bar implementation */ }
};

class Derived : public BarImpl<FooImpl<Abstract> > {
    // You have both foo() and bar() implementations available
};
+5

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


All Articles