Steve
Steve

Reputation: 8293

passing C++11 lambda by templated reference

In gcc 4.5, the following code compiles and works as expected with -std=c++0x,

#include <stdio.h>

template<typename H>
void caller(H h)
{
    h();
}

int main()
{
    auto c = [](){ printf("A\n"); };
    caller(c);
    caller([](){ printf("B\n"); });
    return 0;
}

Prints,

A
B

However, if caller is defined to take a reference,

template<typename H>
void caller(H &h)
{
    h();
}

The compiler complains,

test.cpp: In function ‘int main()’:
test.cpp:61:34: error: no matching function for call to ‘caller(main()::<lambda()>)’
test.cpp:52:6: note: candidate is: void caller(H&) [with H = main()::<lambda()>]

Why?

This seems to break the idea of lambdas providing value semantics for functions, but moreover it means I can't write certain small functions inline which is a bit annoying.

(Is this fixed in newer versions of gcc? I haven't had a chance to test.)

Edit: I just discovered the following actually works:

template<typename H>
void caller(H *h)
{
    (*h)();
}

int main()
{
    auto c = [](){ printf("A\n"); };
    caller(&c);
    caller(&([](){ printf("B\n"); }));
}

I didn't think I'd be able to take the address of a temporary like that. Maybe that sort of solves the problem, though annoying to require users of the function to pass in the address of the closure instead of a convenient reference.

Upvotes: 4

Views: 778

Answers (1)

ecatmur
ecatmur

Reputation: 157344

You're trying to pass a temporary by non-const reference. That won't work for any type.

Pass the lambda by const reference instead.

Upvotes: 6

Related Questions