C++:术语的计算结果不是采用 1 个参数的函数
C++: term does not evaluate to a function taking 1 arguments
我有一个学校的任务,创建一个管理猫收容所的应用程序,我必须提供根据某些标准过滤猫的选项。
我有一个基类 Filter,以及两个派生类,用于按年龄和品种过滤猫。
class Filter
{
public:
virtual bool operator()(const Cat & cat) const = 0;
virtual ~Filter() {}
};
class FilterOfBreed : public Filter
{
private:
std::string breed;
public:
FilterOfBreed(const std::string & b) : breed(b) {}
bool operator()(const Cat & cat) const override { return this->breed.length() == 0 || this->breed == cat.getBreed(); }
};
class FilterAgeLessThan : public Filter
{
private:
int age;
public:
FilterAgeLessThan(int a) : age(a) {}
bool operator()(const Cat & cat) const override { return cat.getAge() <= this->age; }
};
在我的控制器中,我有过滤器功能,它使用copy_if进行过滤。
vector<Cat> Controller::filter(const Filter * filter)
{
vector<Cat> result;
copy_if(this->repo.getCats().begin(), this->repo.getCats().end(), back_inserter(result), filter);
return result;
}
我希望能够使用不同类型的过滤从控制器调用过滤器函数。 例如:
Filter * filter = new FilterOfBreed("Birman");
vector<Cat> filtered = ctrl.filter(filter);
过滤后应包含伯曼品种的猫。
或者对于以下代码:
Filter * filter = new FilterAgeLessThan(3);
vector<Cat> filtered = ctrl.filter(filter);
过滤应包含年龄小于或等于 3 的猫。
为了进行过滤,我需要一个函数来接收两个参数并检查它们之间是否存在某种关系。但是函数"copy_if"必须接收一元谓词作为最后一个参数。我在这里的一篇文章中读到,我可以使用指向 copy_if 中类的指针(该类具有附加参数作为成员),并重载该类的 operator()。这就是我创建类过滤器的原因。
但是当我编译代码时,它给了我一个错误:"术语没有计算为一个接受 1 个参数的函数"。错误来自函数"copy_if"。
>std::copy_if
接受对可调用对象的引用,而不是指向它的指针。 您基本上有两种选择:
-
在不更改函数签名的情况下,进行引用并将其传递给
copy_if
:vector<Cat> Controller::filter(const Filter * filter) { vector<Cat> result; copy_if(repo.getCats().begin(), repo.getCats().end(), back_inserter(result), *filter); // THIS ASTERISK IS THE KEY ^^^ return result; }
-
更改函数以获取引用,就像
copy_if
一样:vector<Cat> Controller::filter(const Filter & filter) // CHANGED TO AMPERSAND HERE ^^^ { vector<Cat> result; copy_if(repo.getCats().begin(), repo.getCats().end(), back_inserter(result), filter); return result; }
与现已删除的评论相反,按值传递不是一种选择。 多态性仅适用于指针和引用,不适用于副本。
此外,对函数对象使用基类也不流行。 现代C++样式通常会为此使用 lambda:
vector<Cat> filtered =
ctrl.filter([](const Cat& cat){ return cat.getBreed() == "Birman"; });
要做到这一点,你可以
使您的筛选函数成为可以接受 lambda 类型的模板:
template<typename Predicate> vector<Cat> Controller::filter(const Predicate & filter) { vector<Cat> result; copy_if(repo.getCats().begin(), repo.getCats().end(), back_inserter(result), filter); return result; }
使用执行类型擦除的
std::function
,这与多态性几乎相同,但不需要继承:vector<Cat> Controller::filter(std::function<bool(const Cat&)> filter) { vector<Cat> result; copy_if(repo.getCats().begin(), repo.getCats().end(), back_inserter(result), filter); return result; }
这两者仍将接受Filter
派生的调用。
相关文章:
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类