Search code examples
c++c++11lambda

Return a reference from lambda


Extending the solution of this question: Pimpl idiom through macro

I want to be able to return reference values from lambda calls:

#include <iostream>
#include <memory>

class FooImp
{
public:
    int& C() { return _value; }

private:
    int _value{};
};

class Foo
{
public:
    Foo() : 
        _imp{ std::make_unique<FooImp>() }
    {
    }

    int& C()
    {
        // In member function 'int& Foo::C()': cannot bind non-const lvalue reference 
        // of type 'int&' to an rvalue of type 'int'
        return call_impl([&] { return _imp->C(); });
    }

private:
    template<typename fn_t>
    auto call_impl(fn_t fn) -> decltype(fn()) 
    {
        std::cout << "Construct Measure here\n";
        
        struct OnExit{
             ~OnExit() { std::cout << "Construct Log here\n"; }
        } onExit;
        return fn();
    }

    std::unique_ptr<FooImp> _imp;
};

int main()
{
    Foo foo;
    std::cout << foo.C() << "\n";
    return 0;
}

This gives me the error:

error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
   24 |         return call_impl([&] { return _imp->C(); });
      |                ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~

because I am not able to return the temporarily created value in the reference. Is there any possible solution to use the call_impl method with references as return values?

Godbolt


Solution

  • The return type should be decltype(auto):

    [&]() -> decltype(auto) {return _imp->C();}
    

    This will copy the return type from the underlying function. Or you can manually write -> int & or -> auto & in this case.