2

I'm trying to pass a local lambda function to a std::bind (for passing to a connect function of a signal):

void f()
{
    auto signal_f = [this](int, int) { /* ... */ };

    namespace ph = std::placeholders;
    signal.connect(std::bind(signal_f, ph::_1, ph::_2));
}

But the function parameter of std::bind is received as a universal reference:

template<class F, class... Args>
/* unspecified */ bind(F&& f, Args&&... args);

So, since my lambda object is a named object, it's passed as a lvalue reference , but my lambda object will be destroyed after f() exists, potentially causing memory leaks when the signal is emited.

What is the simplest way of passing that object by copy?

Of course, I could do always things like:

signal.connect(std::bind<std::decay<decltype(signal_f)>::type>
   (signal_f, ph::_1, ph::_2));

of other tricky ways but they are too cumbersome, so, what is the simplest way of doing it?

NOTE: Is there any function from the standard library to create a copy, something like std::make_rvalue(o) or a std::copy version for objects instead of for containers?

ABu
  • 10,423
  • 6
  • 52
  • 103

2 Answers2

5

If you read the docs for std::bind() you'll see that:

The return type of std::bind holds a member object of type std::decay<F>::type constructed from std::forward<F>(f)

It doesn't hold a reference to signal_f, it holds a copy of it. There is no dependency on the lifetime of signal_f. The only dependency is on the lifetime of this, which signal_f captures.


Note that this:

signal.connect(std::bind<std::decay<decltype(signal_f)>::type>(signal_f, ph::_1, ph::_2));

which is actually the same as this (the decay is pointless since the closure type isn't a reference type):

signal.connect(std::bind<decltype(signal_f)>(signal_f, ph::_1, ph::_2));

is actually the same as:

signal.connect(std::bind(std::move(signal_f), ph::_1, ph::_2));

which you could also do.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • Ok, sorry. I read the documentation but I don't literally "saw" the word **object** ("holds a member **object**"). So, I thought it just had a local `typedef` to the `decay` version of the parameter. – ABu Oct 26 '16 at 17:56
4

bind does not actually store a reference to the lambda. All the parameters are either copied(if lvalue) or moved(if rvalue) into the object returned by bind.

This reason is why you need to use std::ref when passing parameters to bind when the callable takes its parameters by reference.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402