The following code
void CMainWindow::someMethod(const CLocationsCollection& parentItem)
{
auto f = [this, parentItem.displayName](){};
}
gives me an error:
error C2143: syntax error : missing ']' before '.'
If I wanted to catch parentItem.displayName
by ref, I'd make a non-dependent alias identifier for it:
const QString& name = parentItem.displayName;
auto f = [this, &name](){}; // Or should it be [this, name] ?
But I need to capture it by value, and I don't want to capture the whole parentItem
because it's heavy. Any solution?
P. S. Names in the capture list must be identifiers. Isn't parentItem.displayName
(as a whole) an identifier? Why can't it be parsed properly by the compiler?
Note: All standard references in this post are taken from the C++ Standard Draft n3337.
The standard states that a capture must be &
, =
, this
, an identifier, or an identifier preceeded by &
.
5.1.2
Lambda expressions[expr.prim.lambda]
capture-list: capture ..._opt capture-list , capture ..._opt capture: identifier & identifier this
Since parentItem.displayName
is not an identifier, but a "class member access expression". the compiler is correct when rejecting your snippet.
5.2.5p1
Class member access[expr.ref]
A postfix expression followed by a dot
.
or an arrow->
, optionally follow by the keywordtemplate
(14.2), and then followed by an id-expression, is a postfix expression. The postfix expression before the dot or arrow is evaluated;66 the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.
Since C++14 you can use an init-capture to circumvent the issue at hand, looking as the snippet below. It will create a capture with the name display_name, initialized with the value of parentItem.displayName.
[display_name = parentItem.displayName](){ ... };
Sadly such a feature is not available in C++11. The solution to the problem is therefore to make a local reference to the the data-member, and then capture that reference when creating the lambda.
auto& lmb_display_name = parentItem.displayName;
[lmb_display_name](){ ... }; // the lambda will have a copy of `parentItem.displayName`
Note: Your original post seems to imply that the name of a reference R in a lambda's capture-list would make the lambda contain a reference to that which R refers to, something which isn't true, as can be seen by this snippet.