9

标准库函数对象的通常模式是有一个带有非模板的模板结构operator()。例如,std::less看起来像这样:

template <typename T>
struct less
{
    bool operator()(const T& lhs, const T& rhs) const {
        return lhs < rhs;
    }
};

std::vector<float> vec  = ...;
std::sort(vec.begin(), vec.end(), less<float>{});

我的问题是,为什么这比带有模板的非模板结构更好operator()?似乎上述仿函数在操作上等同于:

struct less2
{
    template <typename T>
    bool operator()(const T& lhs, const T& rhs) const {
        return lhs < rhs;
    }
};

std::vector<float> vec = ...;
std::sort(vec.begin(), vec.end(), less2{});

除了我们得到自动类型扣除的奖金。更好的是,如果我们愿意,我们可以比较不同的类型,前提是这样做有意义:

struct less
{
    template <typename T, typename U>
    bool operator()(const T& lhs, const U& rhs) const {
        return lhs < rhs; // compile error if operator<(T, U) is not defined
    }
};

例如,从那里很明显我们可以如何使用decltype来获得真正的通用std::plus。但是标准库不会那样做。

当然,我确信我不是第一个发生这种情况的人,而且我确信标准委员会决定采用第一种模式而不是第二种模式是有充分理由的。我只是不确定它是什么。有哪位大师能开导我吗?

4

1 回答 1

7

在创建原始函子时,确实不存在解决问题所需的语言工具(返回类型推导、完美转发)。当前的设计还具有允许用户为他们自己的类型专门化函子的好处,即使这完全没有必要。

C++1yvoid为所有仿函数引入了特化(并void用作默认参数)以使它们更易于使用。他们将推断并完美地转发参数和返回类型。这也将允许异质比较。

您将能够编写如下代码:

std::sort(begin(v), end(v), less<>());

介绍这一变化的论文是N3421

于 2014-02-12T10:49:20.367 回答