gpt4 book ai didi

c++ - 仿函数与比较器

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:18:04 25 4
gpt4 key购买 nike

我知道仿函数是一个函数对象,是结构定义中 () 运算符的重载。此外,在算法中使用仿函数似乎非常简单,只需调用此例程即可。

但是我无法理解比较器。为什么首先在模板参数中使用它们。

有人可以详细说明两者之间的区别,并可能在 STL 中实现模板,例如 map

编辑:

我正在寻找以下问题的答案

  1. 为什么需要比较器而不是函数对象(而且比较器在容器中更常见?)
  2. 传递比较器而不是函数对象的可能实现(非 STL,即在 C++ 代码中)

最佳答案

您对 仿函数 的定义是正确的 - 虽然该词在语言标准本身中不存在,因此人们使用它的方式可能会略有不同。

标准库中有许多函数或类模板将采用某种可调用对象 - 这可能是仿函数,或指向函数的指针(实际上只是一个函数,而不是带有 operator( )).

比较器 是满足 Compare requirements 类型的对象- 也就是说,可以用两个东西调用并返回 bool 的函数或类对象,特别是满足一些称为严格弱排序的数学要求。

从本质上讲,这意味着比较器是一个仿函数,您可以使用它来按正确的顺序放置一些数字。 (数字、std::stringCustomer 等等,只要有合理一致的方式将它们按顺序排列即可)。

所以使用仿函数的一个简单例子可能是:

void print(int i)
{
std::cout << i << '\n';
}
// ...
std::for_each(std::begin(some_ints), std::end(some_ints), print);

但是如果您想按客户 ID 对一些 Customer 进行排序,您可以这样做:

struct Customer {
std::string surname;
std::string given_name;
std::uint64_t customer_id;
};
bool compareById(Customer const& first, Customer const& second)
// this function meets the Compare requirements
{
return first.customer_id < second.customer_id;
}
// ...
std::sort(std::begin(customers), std::end(customers), compareById);

假设您稍后想要按客户的姓名对客户进行排序 - 首先是姓氏,然后是名字,如果姓氏相同,您可以提供不同的函数:

bool compareByName(Customer const& first, Customer const& second)
{
// std::tie is an idiomatic way to correctly sort on multiple values
return std::tie(first.surname, first.given_name)
< std::tie(second.surname, second.given_name);
}
std::sort(std::begin(customers), std::end(customers), compareByName);

我正在努力发明一个示例,您需要比较器是一个类,但假设您想打印出它对日志文件所做的所有比较;那么该文件将需要由对象存储状态:

struct LoggingCustomerComparator {
std::ostream& logFile;
LoggingCustomerComparator(std::ostream& logFile) : logFile(logFile) {}
bool operator()(Customer const& first, Customer const& second)
{
// assume we have an operator<< for Customer
logFile << "Comparing: " << first << " and " << second << '\n';
return first.customer_id < second.customer_id;
}
};
// ...
using OrderId = std::uint64_t;
using LCC = LoggingCustomerComparator;
std::map<Customer, OrderId, LCC> latestCustomerOrder(LCC(std::clog));
// ^^^ type ^^^ construct object with the log file we want

上面说明了如何使用采用仿函数或比较器的函数模板,但是如果您想编写这样的函数模板怎么办?让我们实现 Bogosort ,以标准库算法的风格:

template <typename RandIt, typename Comp>
void bogosort(RandIt first, RandIt last, Comp comp)
{
std::random_device rd;
std::mt19937 g(rd());

while ( !std::is_sorted(first, last, comp) ) {
std::shuffle(first, last, g);
}
}

查看is_sorted 是如何实现的see here .

关于c++ - 仿函数与比较器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57001655/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com