【发布时间】:2020-09-15 08:26:27
【问题描述】:
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: 模板.cpp:(.text._ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3_[_ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3_]+0x84): 未定义对Predicate<int>::operator()(int const&) const的引用 collect2: error: ld returned 1 exit status 终端进程 以退出代码终止:1
我不太明白HowMuch 中的Prediate<V> 定义有什么问题,因为对我(C++ 新手)来说,它看起来真的是 LGTM。根据我的理解,编译器将Predicate<int> 的定义创建为单独的类型,并且日志准确地说明了这一点,但由于某种原因,它找不到重载调用运算符的类型化定义。可能是类型扣除的问题?容器模板类型本身的模板必须以某种方式显式定义?
编辑:
virtual 修饰符被添加到Predicate 和Producer 的函数运算符重载中,但问题似乎仍然存在。但是,错误“描述”(如果可以称为有用的描述)有所更改(但仍然指向相同的问题):
/tmp/ccn1Swqa.o: 在函数 HowMuch >, int>::operator()(std::__cxx11::list > const&) const: 模板.cpp:(.text._ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3_[_ZNK7HowMuchINSt7__cxx114listIiSaIiEEEiEclERKS3_]+0x76): 未定义对 Predicate::operator()(int const&) const 的引用 /tmp/ccn1Swqa.o:(.rodata._ZTV8ProducerINSt7__cxx114listIiSaIiEEEiE[_ZTV8ProducerINSt7__cxx114listIiSaIiEEEiE]+0x10): 对生产者的未定义引用 >, int>::operator()(std::__cxx11::list > const&) const /tmp/ccn1Swqa.o:(.rodata._ZTV9PredicateIiE[_ZTV9PredicateIiE]+0x10): 未定义对 Predicate::operator()(int const&) const 的引用 collect2: error: ld returned 1 exit status 终端进程 以退出代码终止:1
【问题讨论】:
-
您似乎想要 C++20 概念,而不是这种不必要的继承。
-
@Jarod42 我正在学习 C++ 作为一种支持语言,而不是更多,所以从 Stroustrup 的 C++11 书直接跳到 c++20 标准似乎是不够的,尤其是当问题已经解决时
-
Predicate的目的是什么?似乎不需要。确实当前的答案修复了编译问题,但基类在这里似乎没用。 -
@Jarod42 这段代码显然除了练习我从书中得到的特性之外没有任何用途,而在这里我只是想创建一个 Java 8 端口的功能接口层次结构,看看它是否有效正如预期的那样。它与原始问题有什么关系?但是,无论目的是什么,我都不会阻止您使这段代码成为理想的 sn-p :)
-
Java 解决问题的方式不需要 C++ 方式(对于这种情况)