函子的定义你是对的 - 虽然这个词在语言标准本身中并不存在,所以人们使用它的方式可能会有一些细微的变化。
标准库中有许多函数或类模板将采用某种可调用对象 - 这可能是函子或指向函数的指针(实际上只是一个函数,而不是带有 operator() 的类)。
比较器是一个符合Compare requirements的类型的对象——也就是说,一个函数或类对象可以用两个东西调用并返回一个bool,特别是满足称为严格弱排序的一些数学要求。
本质上,这意味着比较器是一个函子,您可以使用它来将一些数字按正确的顺序排列。 (数字、std::strings、Customers 等等,只要有一种合理一致的方式将它们按顺序排列即可。
所以一个使用仿函数的简单例子可能是:
void print(int i)
{
std::cout << i << '\n';
}
// ...
std::for_each(std::begin(some_ints), std::end(some_ints), print);
但如果您想按客户 ID 对一些 Customers 进行排序,您可以这样做:
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。