template <typename T>
class Predicate {
public:
bool operator()(const T& x) const;
};
template <typename T>
class LessThan : public Predicate<T> {
public:
explicit LessThan(const T& v) : val(v) {}
bool operator()(const T& x) const { return x < val; }
private:
const T val;
};
template <typename C, typename T>
class Producer {
public:
T operator()(const C& c) const;
};
template <typename C, typename V>
class HowMuch : public Producer<C, int> {
public:
explicit HowMuch(Predicate<V> p) : predicate{p} {}
int operator()(const C& c) const {
int count = 0;
for (const auto& x : c)
if (predicate(x)) ++count;
return count;
}
private:
Predicate<V> predicate;
};
int main() {
const LessThan<int> lf(5);
const HowMuch<list<int>, int> hm(lf);
list<int> li {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "How much numbers less than 5 is in {1, 2, 3, 4, 5, 6, 7, 8, 9, "
"10}? Answer: "
<< hm(li)
<< endl;
}
编译上述代码时,g ++将其打印到控制台:
/ tmp / ccblK6El.o:在功能
HowMuch<std::__cxx11::list<int,
中std::allocator<int> >, int>::operator()(std::__cxx11::list<int,
std::allocator<int> > const&) const
:templates.cpp :(。text._ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3 _ [[_ ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3 _] + 0x84):未定义对Predicate<int>::operator()(int const&) const
的引用collect2:错误:ld返回1退出状态终端进程以退出代码终止:1
我不太了解Prediate<V>
中HowMuch
定义的问题所在,因为对我(C ++中的新手)而言,它看起来确实是LGTM。据我了解,编译器将Predicate<int>
的定义创建为单独的类型,日志准确地说明了这一点,但是由于某种原因,它找不到重载的调用运算符的类型化定义。可能是类型推断的问题?容器模板类型本身的模板必须以某种方式明确定义?
编辑:
virtual
修饰符已添加到Predicate
和Producer
的函数运算符重载中,但问题似乎仍然存在。错误“描述”(如果可以称为有用的描述)有所更改,但是(但仍然指向相同的问题):
/ tmp / ccn1Swqa.o:在函数How>>中,int> :: operator()(std :: __ cxx11 :: list> const&)const:templates.cpp :(。text._ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3 _ [[_ ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3 _] + 0x76):未定义对Predicate :: operator()(int const&)const的引用/tmp/ccn1Swqa.o:(.rodata._ZTV8ProducerINSt7__cxx114listIiSaIiEEEiE[_ZTV8ProducerINSt7__cxx114listIiSaIiEEEiE]+0x10):未定义对Producer>的引用,int> :: operator()(std :: __ cxx11 :: list> const&)const/tmp/ccn1Swqa.o:(.rodata._ZTV9PredicateIiE[_ZTV9PredicateIiE]+0x10):未定义对Predicate :: operator()(int const&)const的引用collect2:错误:ld返回1退出状态终端进程以退出代码终止:1
您需要为类的所有功能提供定义。这意味着即使您仅从Predicate
和Producer
派生类,您仍然必须在这些类中实现operator()
。
如果您不想这样做(即仅具有函数声明但没有定义),请考虑通过声明operator()
方法pure virtual来使这两个类abstract。然后,您不能直接从这些类中实例化对象,而只能从实现operator()
方法的derived类中实例化对象。这也意味着您只能在Predicate<V>*
构造函数中传递HowMuch
。