函子与比较器

Gau*_*ant 5 c++ functor comparator c++11

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

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

有人可以详细说明两者之间的区别吗?

编辑:

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

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

BoB*_*ish 7

关于函子的定义,您是对的-尽管在标准语言本身中不存在该词,所以人们的使用方式可能略有不同。

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

一个比较是符合一个类型的对象进行比较的要求 -也就是说,一个函数或类对象,可以用两件事情,并返回一个被称为bool,尤其是遇到一些mathemtical要求需要严格的弱序

本质上,这意味着比较器是一个函子,您可以使用它按正确的顺序放置一些数字。(数字,std::strings,Customers,无论其他什么,只要有一种合理的,一致的方式将它们排序)。

因此,使用函子的一个简单例子可能是:

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

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

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);
Run Code Online (Sandbox Code Playgroud)

假设您稍后要按客户名称对客户进行排序-首先是姓,然后如果姓相同,则给定名称,您可以提供其他功能:

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);
Run Code Online (Sandbox Code Playgroud)

我正在努力创建一个示例,在该示例中,您需要将比较器作为一个类,但是让我们假设您想将其所做的所有比较打印到日志文件中;那么该文件将需要由对象存储状态:

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
Run Code Online (Sandbox Code Playgroud)

以上说明了如何使用该函数模板一个仿函数或比较,但如果你想什么这样的函数模板?让我们以标准库算法的方式实现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);
    }
}
Run Code Online (Sandbox Code Playgroud)

要了解如何is_sorted实现,请参见此处