Наследование в вашем случае кажется неоправданным, вы можете избавиться от своих базовых классов:
template <typename T>
class LessThan {
public:
explicit LessThan(const T& v) : val(v) {}
bool operator()(const T& x) const { return x < val; }
private:
T val;
};
template <typename Predicate>
class HowMuch {
public:
explicit HowMuch(Predicate p) : predicate{p} {}
template <typename Container>
int operator()(const Container& c) const {
int count = 0;
for (const auto& x : c)
if (predicate(x)) ++count;
return count;
}
private:
Predicate predicate;
};
int main() {
const LessThan<int> lf(5);
const HowMuch<LessThan<int>> hm(lf);
std::list<int> li {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::cout << "How much numbers less than 5 is in {1, 2, 3, 4, 5, 6, 7, 8, 9, "
"10}? Answer: "
<< hm(li)
<< std::endl;
}
Demo
Если вам действительно нужен базовый класс в качестве интерфейса , вам нужен чистый виртуальный вызов
template <typename T>
class Predicate {
public:
virtual ~Predicate() = default;
virtual bool operator()(const T& x) const = 0;
};
template <typename C, typename T>
class Producer {
public:
virtual ~Producer() = default;
virtual T operator()(const C& c) const = 0;
};
Также необходимо исправить имеющуюся нарезку объекта:
template <typename C, typename V>
class HowMuch : public Producer<C, int> {
public:
explicit HowMuch(const Predicate<V>& p) : predicate{&p} {}
int operator()(const C& c) const override {
int count = 0;
for (const auto& x : c)
if ((*predicate)(x)) ++count;
return count;
}
private:
const Predicate<V>* predicate;
};
Demo