【问题标题】:Template functors vs functions模板函子与函数
【发布时间】:2015-07-11 16:02:37
【问题描述】:

我一直在查看一些 Boost 源代码并注意到它们通过使用仿函数而不是普通函数来实现模板化函数?这是有原因的吗?

例如:

template<typename Foo, typename Bar>
struct functor {
    Bar operator()(const Foo& foo) {
        return foo.as_bar();
    }
};

相对于:

template<typename Foo, typename Bar>
Bar func(const Foo& foo) {
    return foo.as_bar();
}

我能想到的唯一优点是它允许类继承函数?

【问题讨论】:

    标签: c++ function templates functor


    【解决方案1】:

    有两个主要原因:首先,正如 Python 隐喻所指出的,部分特化只对类有效,对函数无效。请注意,函数通常可以使用重载来克服这个问题,但通常如果您正在进行元编程,使用部分特化更容易和更通用。我实际上认为这是主要原因。

    第二个原因是任何时候代码想要接受一个函数对象(比如在 STL 中,例如 std::transform),它都会有一个类型模板参数。如果您传递一个仿函数或 lambda,则在编译时就知道确切的类型,并且您无需为间接付费,并且可以执行内联。如果您传递函数指针(或 std::function),则在编译时仅知道签名,并且您为间接付费(并且您不能内联)。例如,使用仿函数的 std::sort 可以比使用函数指针快得多。

    请注意,有一个使用过的功能称为函数指针模板参数;这些是专门针对特定功能的非类型模板参数,因此可以删除间接性。但是,如果您使用其中之一,则根本无法使用仿函数。所以大多数想要接受函数对象的代码都是按照我上面描述的方式来做的。

    【讨论】:

    • 我所看到的细节是一种定义色彩空间之间转换的方法,所以我怀疑它确实允许部分专业化。但是,从我读到的内容看来,使用仿函数总是更好的选择?
    • 始终是一个非常强大的术语。你在哪里读到的?函子有它们的优点,但它们也更冗长。重载通常也比部分特化更容易推理。就我个人而言,我会从函数开始,只有当我需要基于通用编程或性能时才使用函子。 Boost 做了很多通用编程,并且必须更加小心性能考虑,因为它们是一个广泛使用的库。实现复杂性对他们来说是最不重要的属性。你(和我)的情况通常不同。
    • 一直都是我自己的推论。谢谢你的解释。
    猜你喜欢
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多