Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an std::function for wrapping a function object

Can someone help me to understand why the following code causes an error?

class A
{
  public:
    float& operator()()
    {
     return _f;
    }

  private:
    float _f = 1;
} a;


auto& foo()
{
  std::function<float()> func = a;
  return func();
}

int main()
{
  std::cout << foo() << std::endl;
}

Error:

error: non-const lvalue reference to type 'float' cannot bind to a temporary of type 'float'
  return func();
         ^~~~~~
1 error generated.

Here, in operator(), I return a reference to _fand consequently, I thought func() is not a temporary. It would be great if someone helps me understand.

like image 282
abraham_hilbert Avatar asked Oct 24 '16 09:10

abraham_hilbert


2 Answers

The problem isn't the use of std::function, its that you're trying to return the temporary float from func() as a reference. This won't work since the object would cease to exist as soon as the statement ends.

If you change auto& foo() to auto foo() it should work.

like image 184
Kiskae Avatar answered Oct 10 '22 04:10

Kiskae


I think you understand that returning a reference to a local variable isn't valid once the variable goes out of scope. What you seem to be missing though is that std::function<float()> func = a; actually creates a local std::function from a. It doesn't point to a in any way, func has it's own A. Which means that calling func(); doesn't actually invoke a.operator() but rather the A of func. Then we get back to the local variable returning a reference is evil part.

To make it compile, you can change your template signature to float&() but it's still undefined behaviour.

A fix would be to change the return type to a copy instead (to auto), removing the reference.

like image 35
Hatted Rooster Avatar answered Oct 10 '22 04:10

Hatted Rooster