标准库函数对象的通常模式是使用带有非模板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
。但标准库并没有这样做。
当然,我确信我不是第一个发生这种情况的人,而且我确信标准委员会决定采用第一种模式而不是第二种模式是有充分理由的。 。我只是不确定它是什么。任何一位大师都能启发我吗?
答案 0 :(得分:7)
当创建原始仿函数时,确实不存在所需的语言设施(返回类型推导,完美转发)来解决问题。目前的设计还有一个好处,即允许用户专门为他们自己的类型设计仿函数,即使这不应该是必要的。
C ++ 1y为所有仿函数引入void
特化(并使用void
作为默认参数),以使它们更易于使用。他们将演绎并完美地转发论证和返回类型。这也将允许异构比较。
您将能够编写如下代码:
std::sort(begin(v), end(v), less<>());
介绍此更改的论文是N3421。