函数:模板化结构与模板化运算符()

Tri*_*dle 9 c++ templates function-object c++-standard-library

标准库函数对象的通常模式是使用带有非模板的模板化结构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>{});
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么这比带有模板化的非模板结构更好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{});
Run Code Online (Sandbox Code Playgroud)

除了我们获得自动类型扣除奖金.更好的是,如果我们想要,我们可以比较不同的类型,只要它有意义:

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

例如,从那里我们可以明白如何使用decltype真正的通用std::plus.但标准库并不是那样做的.

当然,我确信我不是第一个发生这种情况的人,而且我确信标准委员会决定采用第一种模式而不是第二种模式是有充分理由的.我只是不确定它是什么.任何大师都可以启发我吗?

pmr*_*pmr 7

当创建原始仿函数时,确实不存在所需的语言设施(返回类型推导,完美转发)来解决问题.当前的设计还有一个好处,即允许用户专门为自己的类型设计仿函数,即使这种情况严格来说也不是必需的.

C++ 1y void为所有仿函数引入了特化(并void用作默认参数),以使它们更易于使用.他们将演绎并完美地转发论证和返回类型.这也将允许异构比较.

您将能够编写如下代码:

std::sort(begin(v), end(v), less<>());
Run Code Online (Sandbox Code Playgroud)

引入这一变化的论文是N3421.