std :: function vs template [英] std::function vs template

查看:144
本文介绍了std :: function vs template的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于C ++ 11,我们收到了 std :: function 函子包装器的家族。不幸的是,我只听到有关这些新增加的坏话。最流行的是,他们是非常缓慢。我测试了它,他们真的吸引了与模板比较。

Thanks to C++11 we received the std::function family of functor wrappers. Unfortunately, I keep hearing only bad things about these new additions. The most popular is that they are horribly slow. I tested it and they truly suck in comparison with templates.

#include <iostream>
#include <functional>
#include <string>
#include <chrono>

template <typename F>
float calc1(F f) { return -1.0f * f(3.3f) + 666.0f; }

float calc2(std::function<float(float)> f) { return -1.0f * f(3.3f) + 666.0f; }

int main() {
    using namespace std::chrono;

    const auto tp1 = system_clock::now();
    for (int i = 0; i < 1e8; ++i) {
        calc1([](float arg){ return arg * 0.5f; });
    }
    const auto tp2 = high_resolution_clock::now();

    const auto d = duration_cast<milliseconds>(tp2 - tp1);  
    std::cout << d.count() << std::endl;
    return 0;
}

111 ms vs 1241 ms。我假设这是因为模板可以很好地内联,而函数通过虚拟调用覆盖内部。

111 ms vs 1241 ms. I assume this is because templates can be nicely inlined, while functions cover the internals via virtual calls.

模板有他们的问题,我看到他们:

Obviously templates have their issues as I see them:


  • 他们必须提供作为标题,这不是你可能不想做的,当发布您的库作为关闭代码,

  • 他们可能会使编译时间更长,除非引入 extern template li>
  • 没有(至少知道我)干净的方式表示模板的需求(概念,任何人?),bar一个描述什么样的函子的注释。

  • they have to be provided as headers which is not something you might not wish to do when releasing your library as a closed code,
  • they may make the compilation time much longer unless extern template-like policy is introduced,
  • there is no (at least known to me) clean way of representing requirements (concepts, anyone?) of a template, bar a comment describing what kind of functor is expected.

因此,我可以假设 function s可以用作 de facto 传递函数的标准,并且在期望高性能的地方应该使用模板?

Can I thus assume that functions can be used as de facto standard of passing functors, and in places where high performance is expected templates should be used?

编辑:

我的编译器是没有CTP的Visual Studio 2012。

My compiler is the Visual Studio 2012 without CTP.

推荐答案

一般来说,如果您面对的是可以选择的设计情形,请使用使用模板。我强调了设计这个词,因为我认为你需要关注的是 std :: function 和模板之间的区别是很不同。

In general, if you are facing a design situation that gives you a choice, use templates. I stressed the word design because I think what you need to focus on is the distinction between the use cases of std::function and templates, which are pretty different.

一般来说,模板的选择只是一个较宽原则的实例:尽量在编译时指定尽可能多的约束 。原理很简单:如果您可以捕获错误或类型不匹配,即使在生成程序之前,您也不会向您的客户发送错误程序。

In general, the choice of templates is just an instance of a wider principle: try to specify as many constraints as possible at compile-time. The rationale is simple: if you can catch an error, or a type mismatch, even before your program is generated, you won't ship a buggy program to your customer.

此外,正如您正确指出的,调用模板函数是静态解析的(即在编译时),因此编译器具有所有必要的信息,代码(如果调用是通过vtable执行的话是不可能的)。

Moreover, as you correctly pointed out, calls to template functions are resolved statically (i.e. at compile time), so the compiler has all the necessary information to optimize and possibly inline the code (which would not be possible if the call were performed through a vtable).

是的,模板支持是不完美的,而C ++ 11仍然缺乏对概念的支持;然而,我不明白 std :: function 会如何在这方面保存你。 std :: function 不是模板的替代品,而是用于不能使用模板的设计情况的工具。

Yes, it is true that template support is not perfect, and C++11 is still lacking a support for concepts; however, I don't see how std::function would save you in that respect. std::function is not an alternative to templates, but rather a tool for design situations where templates cannot be used.

当您需要通过调用一个符合特定签名但在编译时未知具体类型的可调用对象来解决在运行时 的调用时,会出现一个这样的用例。通常情况下,如果您有一个潜在的不同类型的回调集合,但您需要统一调用;基于程序的状态和应用程序逻辑,在运行时确定注册的回调的类型和数量。其中一些回调可以是函子,一些可以是纯函数,一些可以是将其他函数绑定到某些参数的结果。

One such use case arises when you need to resolve a call at run-time by invoking a callable object that adheres to a specific signature, but whose concrete type is unknown at compile-time. This is typically the case when you have a collection of callbacks of potentially different types, but which you need to invoke uniformly; the type and number of the registered callbacks is determined at run-time based on the state of your program and the application logic. Some of those callbacks could be functors, some could be plain functions, some could be the result of binding other functions to certain arguments.

std: :function std :: bind 也提供了在C ++中启用函数编程的自然习语作为对象,并自然curry和组合生成其他功能。虽然这种组合也可以用模板实现,但是类似的设计情况通常与需要在运行时确定组合的可调用对象的类型的用例一起出现。

std::function and std::bind also offer a natural idiom for enabling functional programming in C++, where functions are treated as objects and get naturally curried and combined to generate other functions. Although this kind of combination can be achieved with templates as well, a similar design situation normally comes together with use cases that require to determine the type of the combined callable objects at run-time.

最后,还有其他情况,其中 std :: function 是不可避免的,例如如果您要写入递归lambda表达式;

Finally, there are other situations where std::function is unavoidable, e.g. if you want to write recursive lambdas; however, these restrictions are more dictated by technological limitations than by conceptual distinctions I believe.

总而言之,关注设计并尝试理解这些限制这两个构造的概念用例是什么。如果你把他们比作你的方式,你强迫他们进入一个竞技场,他们可能不属于。

To sum up, focus on design and try to understand what are the conceptual use cases for these two constructs. If you put them into comparison the way you did, you are forcing them into an arena they likely don't belong to.

这篇关于std :: function vs template的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆