c++ - 仿函数 : templated struct vs templated operator()

标签 c++ templates c++-standard-library function-object

标准库函数对象的通常模式是拥有一个带有非模板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/

相关文章:

c++ - 如何使用函数指针作为类中的参数

c++ - 关于C++模板中自由函数名解析的问题

visual-studio-2013 - MS Visual Studio 2013 中没有 <optional> - 怎么办?

c++ - 是否允许 C++ 标准库实现加强 noexcept 规范?

c++ - 虚拟成员函数和 std::tr1::function:这是如何工作的?

c++ - 您如何构建和引用 libpng?

c++ - 如何在QSortFilterProxyModel中重新排序/移动项目?

python - jinja2 模板中的“if”语句

c++ - 是否为 initializer_list 提供一个私有(private)构造函数?

c++ - 如何处理覆盖某些函数名称的 WinAPI 宏?