P
Paul Bibbings
I'm currently trying to cememt my understanding of n3091
[expr.prim.lambda]. In particular, however, I'm wanting to be sure that
I understand how the constness of the closure type's public function
call operator affects the viability of assignments within its function
body, depending upon whether capture occurs by copy or by reference.
In §5.1.2/5 it says that "This function call operator is declared const
if and only if the lambda-expression's parameter-declaration-clause is
not followed by mutable."
Now, for objects captured by copy the situation appears clear. In
§5.1.2/14 it says "For each entity captured by copy, an unnamed
non-static data member is declared in the closure type." In this
instance it is easy to understand that such unnamed non-static data
members may not be assigned to in the body of the function call operator
on an object of closure type that is not declared mutable.
So, in the following - forgetting for the moment that the `algorithm'
itself fails simply because it has selected capture by copy - the code
fails on the grounds that it omits to add mutable after the
lambda-expression's parameter-declaration-clause:
#include <algorithm>
int main()
{
double d_array[] = { 1.1, 2.2, 3.3, 4.4 };
double sum = 0;
std::for_each(d_array,
d_array + 4,
[=](double d) { // error: not mutable
sum += d;
});
}
What is not clear to me from the specific wording, however, is how this
should behave if we `correct' the code to fit the algorithm and specify
a default capture-by-reference in the lambda-introducer.
Intuitively I would expect the following to be okay:
#include <algorithm>
int main()
{
// as before
std::for_each(d_array,
d_array + 4,
[&](double d) { // OK: not mutable?
sum += d;
});
}
and certainly gcc-4.5.0 agrees:
21:47:59 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $i686-pc-cygwin-gcc-4.5.0 -std=c++0x
-pedantic -c non_mutable_lambda.cpp
21:48:32 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $
However, I then notice where it says - in §5.1.2/15:
"It is unspecified whether additional unnamed non-static data members
are declared in the closure type for entities captured by reference."
To my reading, this appears to introduce an ambiguity over whether the
second example above is valid or not since, where this were to be the
case - that is, where additional non-static data members /are/ declared
for entities captured by reference - it would appear that the assignment
in the function body should fail on the same grounds as for the case of
capture by copy - that it constituted an attempt to assign to a member
of an object of const closure type.
So, any clarification on this point would be accepted gratefully.
Regards
Paul Bibbings
[expr.prim.lambda]. In particular, however, I'm wanting to be sure that
I understand how the constness of the closure type's public function
call operator affects the viability of assignments within its function
body, depending upon whether capture occurs by copy or by reference.
In §5.1.2/5 it says that "This function call operator is declared const
if and only if the lambda-expression's parameter-declaration-clause is
not followed by mutable."
Now, for objects captured by copy the situation appears clear. In
§5.1.2/14 it says "For each entity captured by copy, an unnamed
non-static data member is declared in the closure type." In this
instance it is easy to understand that such unnamed non-static data
members may not be assigned to in the body of the function call operator
on an object of closure type that is not declared mutable.
So, in the following - forgetting for the moment that the `algorithm'
itself fails simply because it has selected capture by copy - the code
fails on the grounds that it omits to add mutable after the
lambda-expression's parameter-declaration-clause:
#include <algorithm>
int main()
{
double d_array[] = { 1.1, 2.2, 3.3, 4.4 };
double sum = 0;
std::for_each(d_array,
d_array + 4,
[=](double d) { // error: not mutable
sum += d;
});
}
What is not clear to me from the specific wording, however, is how this
should behave if we `correct' the code to fit the algorithm and specify
a default capture-by-reference in the lambda-introducer.
Intuitively I would expect the following to be okay:
#include <algorithm>
int main()
{
// as before
std::for_each(d_array,
d_array + 4,
[&](double d) { // OK: not mutable?
sum += d;
});
}
and certainly gcc-4.5.0 agrees:
21:47:59 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $i686-pc-cygwin-gcc-4.5.0 -std=c++0x
-pedantic -c non_mutable_lambda.cpp
21:48:32 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/CLCPPM $
However, I then notice where it says - in §5.1.2/15:
"It is unspecified whether additional unnamed non-static data members
are declared in the closure type for entities captured by reference."
To my reading, this appears to introduce an ambiguity over whether the
second example above is valid or not since, where this were to be the
case - that is, where additional non-static data members /are/ declared
for entities captured by reference - it would appear that the assignment
in the function body should fail on the same grounds as for the case of
capture by copy - that it constituted an attempt to assign to a member
of an object of const closure type.
So, any clarification on this point would be accepted gratefully.
Regards
Paul Bibbings