C++0x lambda capture by value always const?
Use mutable.
auto bar = [=] () mutable -> bool ....
Without mutable you are declaring the operator () of the lambda object const.
C++ lambda capture by value semantic?
You can add mutable
qualifier.
auto testaaa = [testGetStr]() mutable {
// ^^^^^^^
acceptConstString(testGetStr.getString());
};
Otherwise the operator()
of the lambda is const-qualified, and then can't call non-const member functions on the captured object.
- mutable: allows body to modify the objects captured by copy, and to call their non-const member functions
Unless the keyword
mutable
was used in the lambda-expression, the
function-call operator is const-qualified and the objects that were
captured by copy are non-modifiable from inside thisoperator()
.
PS: Or better to make TestGetStr::getString()
const member function.
Lambda Capture by Value forces all scoped object to const
Lambdas behave more or less like function objects; like a function object they have a function call operator, i.e. operator()
. For non-mutable
lambdas, this function is const
:
[expr.prim.lambda]
5 The closure type for a non-generic lambda-expression has a public
inline function call operator [...] This function call operator or
operator template is declaredconst
(9.3.1) if and only if the
lambda-expression’s parameter-declaration-clause is not followed by
mutable
.
Because entities captured by copy behave as though they were member variables of the lambda:
15 [...] For each entity captured by copy, an unnamed non-static data member is declared in the closure type.
and non-mutable
members cannot be modified inside a const
member function ([class.this] / 1, [dcl.type.cv] / 4), if you want to modify the captured entities you will have to declare a mutable
lambda.
As it stands your lambda looks like this:
class Helper
{
public:
int operator()(int) const;
private:
std::map<int, int> memo;
std::function<int(int)> fn;
};
You can think of a mutable
lambda as having a non-const
operator()
, in your case the lambda can be defined as follows:
std::function<int(int)> helper = [=](int pos) mutable
// etc
Why does C++11's lambda require mutable keyword for capture-by-value, by default?
It requires mutable
because by default, a function object should produce the same result every time it's called. This is the difference between an object orientated function and a function using a global variable, effectively.
Binding a const function reference to a lambda
As mentioned already, a capture-less lambda is convertible to a function pointer. So if you want to bind that static function to a reference, you need to dereference the pointer.
int(&foo)(int, int) = *[](int a, int b) { return a + b; };
Applying *
to the lambda causes a bunch of machinery to kick in. Since the lambda doesn't overload operator*
, but does implement a conversion to a pointer type, that conversion happens. Afterwards *
is applied to the returned pointer and that yields a function lvalue. That lvalue can then bind to the reference.
Here it is live.
Return local variable to const ref from lambda
Your lambda returns a prvalue, so the call expression is a temporary object, whose lifetime is extended because it is bound to a reference.
The situation is entirely analogous to the following, simpler example:
int f() { return 12; }
const int& a = f();
Here a
is bound to a temporary object of type int
and value 12
.
If you do not specify the return type of a lambda, the return type is always either void
or an object type. If you want your lambda to return an lvalue or xvalue, you will explicitly need to specify the return type, e.g. as -> int&
, -> auto&
, -> decltype(auto)
, etc.
const static auto lambda used with capture by reference
A static function-scope variable is initialised "lazily," when control flow first reaches its declaration. This means that the capture by reference does indeed bind to the foo
currently on stack, and when the call terminates, that binding becomes dangling.
Don't try to help the compiler too much; making lambda
static
looks like a micro-optimisation, with very bad side effects. There's next to no overhead involved in actually creating a closure object, and the compiler can easily inline it regardless of whether it's static
or not.
Not to mention the fact that you're not saving on creating the std::function
object even with your approach. The type of a lambda expression is an unnamed closure object, not std::function
. So even if lambda
is static
, the std::function
object is created in each call anyway (unless the whole thing is inlined).
Related Topics
Why Doesn't C++ Support Functions Returning Arrays
How to Check If a C++ String Is an Int
Using Strtok With a Std::String
C++ Dll Export: Decorated/Mangled Names
How to Programmatically Get the Version of a Dll or Exe File
Requesting Administrator Privileges At Run Time
Sfinae to Check For Inherited Member Functions
How Does a C++ Reference Look, Memory-Wise
Conversion Constructor Vs. Conversion Operator: Precedence
How to Catch Segmentation Fault in Linux
When to Overload the Comma Operator
Experimental::Filesystem Linker Error
Stringstream, String, and Char* Conversion Confusion
Confused When Boost::Asio::Io_Service Run Method Blocks/Unblocks