-2

I want to have a base class with datatypes that will be defined in derived class.

pseudo code

class Base{
 public:
  void Enroll(vector<int> v){
    feature_list.emplace_back(ExtractFeature1(v));
  }

  vector<double> Compare(vector<int> v){
    FeatureType2 ft2 = ExtractFeature2(v);
    vector<double> scores;
    for (auto &ft1:feature_list){
      scores.emplace_back(Compare(ft1, ft2));
    }
    return scores;
  }

 protected:
  vector<FeatureType1> feature_list;

  virtual FeatureType1 ExtractFeature1(vector<int> v)=0;
  virtual FeatureType2 ExtractFeature2(vector<int> v)=0;
  virtual double Compare(FeatureType1 f1,FeatureType2 f2)=0; 
}

So each derived class will implement a different way of extracting and comparing features.

I don't know how to do set some kinds of placeholder type for FeatureType1 and FeatureType2 in Base class and then force Derived class to define them. Any advice or guidance would be greatly appreciated.

D R
  • 21
  • 7

1 Answers1

0

I want to have a base class with datatypes that will be defined in derived class.

Well, you can't quite do that: The base class has to be completely defined for you to derive classes from it.

What you can do, however, is use the Curiously-Recurring Template Pattern (CRTP):

template <typename T>
class Base {
    using data_type = typename T::data_type;
        // this will be a different type for each T - and
        // we don't need to know it in advance

    void Enroll(const vector<int>& v){
        // implementation that can depend on T in many ways.
        // Specifically, you can use `data_type`.
    }

    vector<double> Compare(const vector<int>& v){ /* ... */ }

    // ...
 };

 class SomeDerived : Base<SomeDerived> { /* ... */ };
 class AnotherDerived : Base<AnotherDerived> { /* ... */ };

The classes SomeDerived and AnotherDerived don't actually have the same base class, but their base classes are instantiations of the same template, so you avoid code duplication. And - you have the "base" class using types defined in the derived class, as long as they're defined in the same way.

Edit (thanks @Aconcagua): You might not need to go as far as the full CRTP. If the only thing your base class needs to know regarding the derived class is the data type, then just template the base class on that, i.e.

template <typename DataType>
class Base {
    using data_type = DataType;
    // ... as before...
};

 class SomeDerived : Base<some_data_type> { /* ... */ };
 class AnotherDerived : Base<another_data_type> { /* ... */ };
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • This is what I thought of right from the start, too, but possibly we can live without CRTP: `class SomeDerived : Base {}; class AnotherDerived : Base {};` According to the question, we probably need two feature template parameters, though? – Aconcagua Apr 03 '18 at 19:32
  • I did try to use template at the beginning. However since I want to use something like `Base *b = new SomeDerived(); /*..*/ b = new AnotherDerived()`. But CRTP is new to me. Much appreciated for introducing that. – D R Apr 03 '18 at 19:44