6

I'm working on a small mathematical optimization framework in C++11, and I wonder what's the best way for the user to provide domain-specific logic. I could force her to define classes with hook methods that can be called by the framework, but I'd like to keep it lean and take advantage of the new C++11 facilities whenever I can. So I'm thinking about accepting std::function objects, possibly instantiated from lambda expressions, as parameters, and call them when needed. The only think I'm wondering about is whether the compiler (in my case gcc, but I'd like to know about Xcode and Visual C++ as well) will be able to take the std::function objects and inline the function definitions, so that they are optimized together with the rest of the code.

PS: from the comments, it looks like the first revision of my question was obscure to most of the users, probably my fault for using an incorrect language. So I have reworded it, I hope someone can understand the concept I'm trying to convey here (and possibly suggest a solution).

PPS: someone suggested to use templates, that is an idea I have thought about, but I'd like to know if there's an alternative. I don't have anything against templates, but I plan to make a template-based version as soon as this one is working because I find it easier to reason in terms of dynamic objects.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
tunnuz
  • 23,338
  • 31
  • 90
  • 128
  • What about... templates? – Xeo May 24 '13 at 08:15
  • I plan to use templates for compile-time optimization as soon as the first version is working. – tunnuz May 24 '13 at 08:19
  • Compile std::function object away ? What does that mean ? – Arzar May 24 '13 at 08:27
  • 1
    It's clearer now. std::function is by no mean light or lean. It's a quite complicated polymorphic wrapper that has lot of features which come with a cost. std::function make some heap allocation for example ! I don't know about GCC, but in visual studio std::function is a brickwall to optimization so you will have an indirect call. If you want inlining use a template as a parameter instead of std::function. – Arzar May 24 '13 at 09:02
  • @ThomasPetit excellent, that explained it. Would you like to put this in form of a reply, so that I can upvote and close the question? – tunnuz May 24 '13 at 09:18
  • 3
    I described some of the implementation details of GCC's `std::function` (and how they affect optimization) at http://stackoverflow.com/a/11127742/981959 – Jonathan Wakely May 24 '13 at 11:03

1 Answers1

8

std::function is a callable object which can store any callable object. It is as flexible as possible, by design. That design however comes with drawbacks. Because functions could contain pretty much anything (callable), they must be able to work with anything.

Internally, function has no idea at compile-time what it might be storing. Since this determination is made a runtime, it is pretty much impossible for most normal compilers to inline through that. Inlining through a function pointer is possible, but only if it's locally known what the value of that pointer is. function is a lot more complex than a mere function pointer.

It is theoretically possible to inline such a thing, but only as part of some kind of profile-guided optimization system, where repeated execution of the code is able to determine that certain function objects will always be used with certain contents and thus to inline them. But even that is

If you want inlining for an arbitrary callable object, you should use a template function, not std::function. function is for when you can't use templates (perhaps because you need to store multiple functions in a container, or because you don't want to break encapsulation, or whatever), yet still need to store arbitrary callables.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • The cost of calling a `std::function` is similar to the cost of calling `struct foo { virtual void do_stuff() = 0; }`. The marginal cost of creating a `std::function` is the cost of copying the underlying type (which can be a function pointer, a lambda, or whatever), plus a free store (heap) allocation modestly larger than the underlying type. The fixed cost of creating a `std::function` is the code created by the `template` constructor, which creates a `pImpl` type class, with a `virtual` function table. (This assumes a relatively conventional implementation of `std::function`) – Yakk - Adam Nevraumont May 24 '13 at 17:48
  • @Yakk: Note that some implementations do use small object optimization to avoid the heap allocation in cases where that's possible. – Nicol Bolas May 24 '13 at 17:50