41

How do I assign a lambda as default argument? I would like to do this:

int foo(int i, std::function<int(int)> f = [](int x) -> int { return x / 2; }) { return f(i); } 

but my compiler (g++ 4.6 on Mac OS X) complains:

error: local variable 'x' may not appear in this context 

EDIT: Indeed, this was a compiler bug. The above code works fine with a recent version of gcc (4.7-20120225).

4
  • I wonder if it's an issue with gcc or if the standard forbids it. Commented May 17, 2011 at 6:33
  • 2
    Just to add, MSVC (2010) spews the same warning: error C2587: 'x' : illegal use of local variable as default parameter - see declaration of 'x'. It seems to because of the parameter, if I remove it from the lambda, std::function and function call, it compiles perfectly fine. Commented May 17, 2011 at 17:45
  • @Xeo: I wonder how VC2011 reacts to this syntax, since it has improved lambda support. Commented Mar 5, 2012 at 23:34
  • Works now (Feb 24, 2017) with clang-800.0.42.1 via clang++ -c -std=c++11 Commented Feb 24, 2017 at 20:33

2 Answers 2

28

You could use overloading:

int foo(int i) { return foo(i, [](int x) -> int { return x / 2; }); } int foo(int i, std::function<int(int)> f) { return f(i); } 
Sign up to request clarification or add additional context in comments.

2 Comments

Like Matthieu, I am not sure whether the issue is a bug in gcc or intentional. Your workaround seems the best solution at the moment.
Ahh, java-style default parameters. A sight for sore eyes (not!)
9

This seems to be a bug in gcc; the standard permits lambda expressions in default parameters as long as nothing is captured.

The following seems to be everything the FDIS says about lambdas in default parameters, so any use other than what is forbidden here ought to be permitted by default.

C++11 FDIS 5.1.2/13

A lambda-expression appearing in a default argument shall not implicitly or explicitly capture any entity.

[ Example:

void f2() { int i = 1; void g1(int = ([i]{ return i; })()); // ill-formed void g2(int = ([i]{ return 0; })()); // ill-formed void g3(int = ([=]{ return i; })()); // ill-formed void g4(int = ([=]{ return 0; })()); // OK void g5(int = ([]{ return sizeof i; })()); // OK } 

— end example ]

4 Comments

Note that, in all those examples there is no parameter, and that's what the compiler chokes on (even in VS2010).
@Xeo - Yeah, but nowhere in the standard does it explicitly forbid parameters in lambdas used as default argument (that would be a very silly restriction indeed), so both compilers are simply buggy.
These examples are slightly different -- these are executing a lambda to obtain a function argument's default value; does this really imply that the lambda itself can be a default value?
@ildjarn - The example itself is non-normative, but the grammar clearly permits a default argument that is a lambda expression, and AFAICS there exists no normative text that specifically makes an exception to what the grammar says.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.