最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - cannot bind non-const when trying to return reference to global from lambda - Stack Overflow

programmeradmin5浏览0评论

I'm trying to get a lambda to return a reference to global. My MCVE is

static int frob;

int& foo();

template <typename F>
auto bar(F f)
{
    return f();
}

int& foo()
{
    return bar([&](){
        return frob;
    });

    // int* p;
    // bar([&](){
    //     p = &frob;
    // });
    // return *p;
}

Using the outcommented implementation of foo passes compilation, but otherwise I get (from gcc 12.2.0)

error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’

I tried to create an int& inside foo to hold the reference to frob land (in hope that it would make the returned expression an int&), but that didn't help. Also moving frob into foo or even the lambda didn't help either, however it's not an alternative in my actual case anyway.

I'm a bit confused by the error so the question is first why do I get the error in the first place (and second how can I get around it, still transporting the result out of the lambda via return statement).

I'm trying to get a lambda to return a reference to global. My MCVE is

static int frob;

int& foo();

template <typename F>
auto bar(F f)
{
    return f();
}

int& foo()
{
    return bar([&](){
        return frob;
    });

    // int* p;
    // bar([&](){
    //     p = &frob;
    // });
    // return *p;
}

Using the outcommented implementation of foo passes compilation, but otherwise I get (from gcc 12.2.0)

error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’

I tried to create an int& inside foo to hold the reference to frob land (in hope that it would make the returned expression an int&), but that didn't help. Also moving frob into foo or even the lambda didn't help either, however it's not an alternative in my actual case anyway.

I'm a bit confused by the error so the question is first why do I get the error in the first place (and second how can I get around it, still transporting the result out of the lambda via return statement).

Share Improve this question edited 17 hours ago Some programmer dude 409k36 gold badges413 silver badges643 bronze badges asked 17 hours ago skykingskyking 14.4k2 gold badges37 silver badges61 bronze badges 2
  • 2 Both the lambda and the bar function returns the integer by value. If you want to return a reference you must explicitly say so (e.g. [&]() -> int& { return frob; }) – Some programmer dude Commented 17 hours ago
  • 2 Read about how auto works. – Passer By Commented 17 hours ago
Add a comment  | 

1 Answer 1

Reset to default 6

auto is deduced to T, not T& in both bar and lambda's return type. auto& would be necessary.

So you either have to use auto& annotations

static int frob;

int& foo();

template <typename F>
auto& bar(F f)
{
    return f();
}

int& foo()
{
    return bar([&]() -> auto&{
        return frob;
    });

}

or, alternatively, if you do not care about their true return types, std::ref can do the trick as it can carry references using value semantics and "unpack" them by implicit conversion to T& whenever necessary.

#include <functional>
static int frob;

int& foo();

template <typename F>
auto bar(F f)
{
    return f();
}

int& foo()
{
    return bar([&](){
        return std::ref(frob);
    });

}
发布评论

评论列表(0)

  1. 暂无评论