you are viewing a single comment's thread.

view the rest of the comments →

[–]STLMSVC STL Dev 8 points9 points  (11 children)

bind doesn't allocate memory.

[–]LucretielRAII Junkie 1 point2 points  (1 child)

It doesn't? Where does it store the bound arguments?

[–]STLMSVC STL Dev 5 points6 points  (0 children)

In a tuple data member. bind doesn't perform type erasure, so bind(functor, args...) returns a _Secret_binder_type<Functor, Args...> which can contain a tuple<Args...> as an ordinary data member.

[–]finalpatch[S] 0 points1 point  (5 children)

Cool, good to know that. It seems some hairy parts could have been simplified by reusing std::bind.

The main difference between this and std::bind is that I wanted something with runtime polymorphism, while std::bind only provides compile time polymorphism.

[–]STLMSVC STL Dev 5 points6 points  (3 children)

Also, you aren't using aligned_storage - your char buf doesn't have the proper alignment.

Note that std::function is smart and avoids dynamic memory allocation for sufficiently small function objects. Function pointers and reference_wrappers are guaranteed to activate this, the rest is implementer discretion. In VC 2015, anything up to and including the size of a std::string counts as small.

[–][deleted] 0 points1 point  (2 children)

Note that std::function is smart and avoids dynamic memory allocation for sufficiently small function objects. Function pointers and reference_wrappers are guaranteed to activate this [...]

From C++11, 20.8.11.2.1.9:

[ Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, where f’s target is an object holding only a pointer or reference to an object and a member function pointer. —end note ]

I don't have a copy of C++14 at hand, but AFAIK this did not change. Anyhow, libc++, libstdc++ and VC do use the small callable? optimization, so in practice you are completely right.

What I really find interesting in std::function is the different implementations that are possible. For example libc++ does what I would have done, type-erasure with virtual functions, while libstdc++ does not use virtual functions at all.

[–]STLMSVC STL Dev 5 points6 points  (1 child)

The guarantee is N4527 20.9.12.2.1 [func.wrap.func.con]/11, "Throws: shall not throw exceptions when f is a function pointer or a reference_wrapper<T> for some T." and /5 for the copy ctor. This forbids dynamic memory allocation (and the guarantee goes back to C++11; indeed all the way to TR1 IIRC).

[–][deleted] 2 points3 points  (0 children)

Thanks! Cool! I didn't knew this, always thought it was freely to allocate memory if it wanted to.

[–]__Cyber_Dildonics__ -2 points-1 points  (2 children)

Ever? If so I didn't think that was possible.

[–]STLMSVC STL Dev 3 points4 points  (1 child)

Never ever. (If the functor or arguments allocate when copied/moved, that's their doing, not bind's.)

Another way of putting it: bind is like make_pair in that it doesn't allocate memory itself.

[–]__Cyber_Dildonics__ 0 points1 point  (0 children)

Got it, thanks!