Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable cannot be implicitly captured in a lambda with no capture-default specified

I'm following this guy's blog post on C++ Lambdas http://cpptruths.blogspot.com/2014/03/fun-with-lambdas-c14-style-part-1.html and while compiling his code, I ran into a compiler error:

variable 'unit' cannot be implicitly captured in a lambda with no capture-default specified"

The lines that it is referencing are below:

auto unit = [](auto x) {
    return [=](){ return x; };
};
auto stringify = [](auto x) {
    stringstream ss;
    ss << x;
    return unit(ss.str());
};

The guy seems like he knows about the new Lambda features in C++, which I certainly do not, which is why I am here now. Can someone shed some light on this problem? What do I need to do to get this code compiling correctly?

Thanks in advance! :)


edit: Turns out the problem wasn't with unit or stringify. Let me paste the new code:

auto unit = [](auto x) {
    return [=](){ return x; };
};

auto stringify = [unit](auto x) {
    stringstream ss;
    ss << x;
    return unit(ss.str());
};

auto bind = [](auto u) {
    return [=](auto callback) {
        return callback(u());
    };
};

cout << "Left identity: " << stringify(15)() << "==" << bind(unit(15))(stringify)() << endl;
cout << "Right identity: " << stringify(5)() << "==" << bind(stringify(5))(unit)() << endl;
//cout << "Left identity: " << stringify(15)() << endl;
//cout << "Right identity: " << stringify(5)() << endl;

Ok, so, the call to "bind" is what is causing the following error:

"__ZZZ4mainENK4$_17clINSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEEEEDaT_ENUlvE_C1ERKSA_", referenced from:
  std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > main::$_19::operator()<auto main::$_17::operator()<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) const::'lambda'()>(auto main::$_17::operator()<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) const::'lambda'()) const in funwithlambdas-0f8fc6.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [funwithlambdas] Error 1

I'll play around with it a bit more and if I fix it I will post here, but please post your solution or comment if you are able to. Thanks again!

like image 229
Mike Bell Avatar asked Oct 31 '22 22:10

Mike Bell


1 Answers

There you go:

auto unit = [](auto x) {
    return [=](){ return x; };
};
auto stringify = [unit](auto x) { // or '&unit
    stringstream ss;
    ss << x;
    return unit(ss.str());
};

Lambdas don't capture anything of outer-scope, you must specify it.

EDIT: User 'T.C.' is right - both of the lambdas are global in that article. In that case unit gets accessed without specification. And with specification (which I gave), it fails in VC2015.

like image 131
Ajay Avatar answered Nov 15 '22 05:11

Ajay