标准库函数对象的通常模式是拥有一个带有非模板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
,例如。但是标准库不会那样做。
当然,我确信我不是第一个发生这种情况的人,而且我确信标准委员会决定采用第一种模式而不是第二种模式是有充分理由的.我只是不确定它是什么。有哪位大侠能赐教吗?
最佳答案
当最初的仿函数被创建时,没有任何需要的语言设施(返回类型推导、完美转发)来解决这个问题。当前的设计还有一个好处,即允许用户为他们自己的类型专门化仿函数,即使这完全没有必要。
C++1y 为所有仿函数引入了 void
特化(并使用 void
作为默认参数),使它们更易于使用。他们将推导并完美地转发参数和返回类型。这也将允许异构比较。
您将能够编写如下代码:
std::sort(begin(v), end(v), less<>());
介绍这个变化的论文是N3421 .
关于c++ - 仿函数 : templated struct vs templated operator(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21725475/