Why is a lambda's call-operator implicitly const?











up vote
13
down vote

favorite
2












I have a small "lambda expression" in the below function:



int main()
{
int x = 10;
auto lambda = [=] () { return x + 3; };
}


Below is the "anonymous closure class" generated for the above lambda expression.



int main()
{
int x = 10;

class __lambda_3_19
{
public: inline /*constexpr */ int operator()() const
{
return x + 3;
}

private:
int x;

public: __lambda_3_19(int _x) : x{_x}
{}

};

__lambda_3_19 lambda = __lambda_3_19{x};
}


The closure's "operator()" generated by the compiler is implicitly const. Why did the standard committee make it const by default?










share|improve this question




















  • 9




    @Bathsheba from what I understand it's compiler-generated, so no UB there
    – Ap31
    2 days ago






  • 3




    There is an school of thought that all variables should be const by default. Perhaps this kind of thinking had some influence?
    – Galik
    2 days ago






  • 1




    @gurram I think the question should be why not? what could be the reason for making it non-const, thus limiting your lambda for no reason?
    – Ap31
    2 days ago






  • 2




    @gurram Think about capturing a pointer by value, which copies the pointer and not what it points to. If you're able to call non-const functions of the object, then that could modify the object, possibly in ways that are unwanted or leads to UB. If the operator() function is marked as const then that's not possible.
    – Some programmer dude
    2 days ago








  • 2




    Its the wrong way around that we have to declare member functions explicitly as const and non-const is the default. Its weird that we are used to redundantly repeat the return type of a function when auto return types could be natural. In some sense lambdas give you a glimpse of how c++ could look like if it was reinvented from scratch today.
    – user463035818
    2 days ago

















up vote
13
down vote

favorite
2












I have a small "lambda expression" in the below function:



int main()
{
int x = 10;
auto lambda = [=] () { return x + 3; };
}


Below is the "anonymous closure class" generated for the above lambda expression.



int main()
{
int x = 10;

class __lambda_3_19
{
public: inline /*constexpr */ int operator()() const
{
return x + 3;
}

private:
int x;

public: __lambda_3_19(int _x) : x{_x}
{}

};

__lambda_3_19 lambda = __lambda_3_19{x};
}


The closure's "operator()" generated by the compiler is implicitly const. Why did the standard committee make it const by default?










share|improve this question




















  • 9




    @Bathsheba from what I understand it's compiler-generated, so no UB there
    – Ap31
    2 days ago






  • 3




    There is an school of thought that all variables should be const by default. Perhaps this kind of thinking had some influence?
    – Galik
    2 days ago






  • 1




    @gurram I think the question should be why not? what could be the reason for making it non-const, thus limiting your lambda for no reason?
    – Ap31
    2 days ago






  • 2




    @gurram Think about capturing a pointer by value, which copies the pointer and not what it points to. If you're able to call non-const functions of the object, then that could modify the object, possibly in ways that are unwanted or leads to UB. If the operator() function is marked as const then that's not possible.
    – Some programmer dude
    2 days ago








  • 2




    Its the wrong way around that we have to declare member functions explicitly as const and non-const is the default. Its weird that we are used to redundantly repeat the return type of a function when auto return types could be natural. In some sense lambdas give you a glimpse of how c++ could look like if it was reinvented from scratch today.
    – user463035818
    2 days ago















up vote
13
down vote

favorite
2









up vote
13
down vote

favorite
2






2





I have a small "lambda expression" in the below function:



int main()
{
int x = 10;
auto lambda = [=] () { return x + 3; };
}


Below is the "anonymous closure class" generated for the above lambda expression.



int main()
{
int x = 10;

class __lambda_3_19
{
public: inline /*constexpr */ int operator()() const
{
return x + 3;
}

private:
int x;

public: __lambda_3_19(int _x) : x{_x}
{}

};

__lambda_3_19 lambda = __lambda_3_19{x};
}


The closure's "operator()" generated by the compiler is implicitly const. Why did the standard committee make it const by default?










share|improve this question















I have a small "lambda expression" in the below function:



int main()
{
int x = 10;
auto lambda = [=] () { return x + 3; };
}


Below is the "anonymous closure class" generated for the above lambda expression.



int main()
{
int x = 10;

class __lambda_3_19
{
public: inline /*constexpr */ int operator()() const
{
return x + 3;
}

private:
int x;

public: __lambda_3_19(int _x) : x{_x}
{}

};

__lambda_3_19 lambda = __lambda_3_19{x};
}


The closure's "operator()" generated by the compiler is implicitly const. Why did the standard committee make it const by default?







c++ c++11 lambda const function-call-operator






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









max66

32.8k63660




32.8k63660










asked 2 days ago









gurram

17711




17711








  • 9




    @Bathsheba from what I understand it's compiler-generated, so no UB there
    – Ap31
    2 days ago






  • 3




    There is an school of thought that all variables should be const by default. Perhaps this kind of thinking had some influence?
    – Galik
    2 days ago






  • 1




    @gurram I think the question should be why not? what could be the reason for making it non-const, thus limiting your lambda for no reason?
    – Ap31
    2 days ago






  • 2




    @gurram Think about capturing a pointer by value, which copies the pointer and not what it points to. If you're able to call non-const functions of the object, then that could modify the object, possibly in ways that are unwanted or leads to UB. If the operator() function is marked as const then that's not possible.
    – Some programmer dude
    2 days ago








  • 2




    Its the wrong way around that we have to declare member functions explicitly as const and non-const is the default. Its weird that we are used to redundantly repeat the return type of a function when auto return types could be natural. In some sense lambdas give you a glimpse of how c++ could look like if it was reinvented from scratch today.
    – user463035818
    2 days ago
















  • 9




    @Bathsheba from what I understand it's compiler-generated, so no UB there
    – Ap31
    2 days ago






  • 3




    There is an school of thought that all variables should be const by default. Perhaps this kind of thinking had some influence?
    – Galik
    2 days ago






  • 1




    @gurram I think the question should be why not? what could be the reason for making it non-const, thus limiting your lambda for no reason?
    – Ap31
    2 days ago






  • 2




    @gurram Think about capturing a pointer by value, which copies the pointer and not what it points to. If you're able to call non-const functions of the object, then that could modify the object, possibly in ways that are unwanted or leads to UB. If the operator() function is marked as const then that's not possible.
    – Some programmer dude
    2 days ago








  • 2




    Its the wrong way around that we have to declare member functions explicitly as const and non-const is the default. Its weird that we are used to redundantly repeat the return type of a function when auto return types could be natural. In some sense lambdas give you a glimpse of how c++ could look like if it was reinvented from scratch today.
    – user463035818
    2 days ago










9




9




@Bathsheba from what I understand it's compiler-generated, so no UB there
– Ap31
2 days ago




@Bathsheba from what I understand it's compiler-generated, so no UB there
– Ap31
2 days ago




3




3




There is an school of thought that all variables should be const by default. Perhaps this kind of thinking had some influence?
– Galik
2 days ago




There is an school of thought that all variables should be const by default. Perhaps this kind of thinking had some influence?
– Galik
2 days ago




1




1




@gurram I think the question should be why not? what could be the reason for making it non-const, thus limiting your lambda for no reason?
– Ap31
2 days ago




@gurram I think the question should be why not? what could be the reason for making it non-const, thus limiting your lambda for no reason?
– Ap31
2 days ago




2




2




@gurram Think about capturing a pointer by value, which copies the pointer and not what it points to. If you're able to call non-const functions of the object, then that could modify the object, possibly in ways that are unwanted or leads to UB. If the operator() function is marked as const then that's not possible.
– Some programmer dude
2 days ago






@gurram Think about capturing a pointer by value, which copies the pointer and not what it points to. If you're able to call non-const functions of the object, then that could modify the object, possibly in ways that are unwanted or leads to UB. If the operator() function is marked as const then that's not possible.
– Some programmer dude
2 days ago






2




2




Its the wrong way around that we have to declare member functions explicitly as const and non-const is the default. Its weird that we are used to redundantly repeat the return type of a function when auto return types could be natural. In some sense lambdas give you a glimpse of how c++ could look like if it was reinvented from scratch today.
– user463035818
2 days ago






Its the wrong way around that we have to declare member functions explicitly as const and non-const is the default. Its weird that we are used to redundantly repeat the return type of a function when auto return types could be natural. In some sense lambdas give you a glimpse of how c++ could look like if it was reinvented from scratch today.
– user463035818
2 days ago














3 Answers
3






active

oldest

votes

















up vote
8
down vote



accepted










From cppreference




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 this operator()




In your case, there is nothing that, captured by copy, is modifiable.



I suppose that, if you write something as



int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };


the const should disappear



-- EDIT --



The OP precise




I already knew that adding mutable will solve the issue. The question is that I want to understand the reason behind making the lambda immutable by default.




I'm not a language lawyer but this seems me obvious: if you make operator() not const, you can't make something as



template <typename F>
void foo (F const & f)
{ f(); }

// ...

foo({ std::cout << "lambda!" << std::endl; });


I mean... if operator() isn't const, you can't use lambdas passing they as const reference.



And when isn't strictly needed, should be an unacceptable limitation.






share|improve this answer























  • Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
    – Deduplicator
    2 days ago












  • @Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
    – max66
    2 days ago






  • 1




    @Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
    – liliscent
    2 days ago




















up vote
18
down vote













Found this paper by Herb Sutter at open-std.org which discusses this matter.




The odd couple: Capture by value’s injected const and quirky mutable

Consider this strawman example, where the programmer captures a local variable by value and tries to modify the captured value (which is a member variable of the lambda object):



int val = 0;
auto x = [=]( item e ) // look ma, [=] means explicit copy
{ use( e, ++val ); }; // error: count is const, need ‘mutable’
auto y = [val]( item e ) // darnit, I really can’t get more explicit
{ use( e, ++val ); }; // same error: count is const, need ‘mutable’


This feature appears to have been added out of a concern that the user might not realize he got a copy, and in particular that since lambdas are copyable he might be changing a different lambda’s copy.




The above quote and example indicate why the Standards Committee might have made it const by default and required mutable to change it.






share|improve this answer



















  • 1




    The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
    – ShadowRanger
    2 days ago












  • @ShadowRanger: That's how I understand it. I did not test it though.
    – P.W
    2 days ago


















up vote
0
down vote













I think, it is simply to avoid confusion when a variable inside a lambda refer not to what was originally captured. Lexically such a variable is as if in scope of its "original". Copying is mainly to allow to extend the lifetime of object. When a capture is not by copy it refers to original and modifications are applied to the original, and there is no confusion because of two different objects (one of which is implicitly introduced), and it is allowed by lambda's const function call operator.






share|improve this answer








New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • but why I cannot edit my posts??
    – guest
    2 days ago










  • You should be able to. Just click the edit link here.
    – wizzwizz4
    2 days ago










  • "Page Not Found" is the result.
    – guest
    2 days ago










  • Post a bug report on Meta Stack Overflow. That's strange...
    – wizzwizz4
    2 days ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53445857%2fwhy-is-a-lambdas-call-operator-implicitly-const%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
8
down vote



accepted










From cppreference




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 this operator()




In your case, there is nothing that, captured by copy, is modifiable.



I suppose that, if you write something as



int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };


the const should disappear



-- EDIT --



The OP precise




I already knew that adding mutable will solve the issue. The question is that I want to understand the reason behind making the lambda immutable by default.




I'm not a language lawyer but this seems me obvious: if you make operator() not const, you can't make something as



template <typename F>
void foo (F const & f)
{ f(); }

// ...

foo({ std::cout << "lambda!" << std::endl; });


I mean... if operator() isn't const, you can't use lambdas passing they as const reference.



And when isn't strictly needed, should be an unacceptable limitation.






share|improve this answer























  • Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
    – Deduplicator
    2 days ago












  • @Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
    – max66
    2 days ago






  • 1




    @Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
    – liliscent
    2 days ago

















up vote
8
down vote



accepted










From cppreference




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 this operator()




In your case, there is nothing that, captured by copy, is modifiable.



I suppose that, if you write something as



int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };


the const should disappear



-- EDIT --



The OP precise




I already knew that adding mutable will solve the issue. The question is that I want to understand the reason behind making the lambda immutable by default.




I'm not a language lawyer but this seems me obvious: if you make operator() not const, you can't make something as



template <typename F>
void foo (F const & f)
{ f(); }

// ...

foo({ std::cout << "lambda!" << std::endl; });


I mean... if operator() isn't const, you can't use lambdas passing they as const reference.



And when isn't strictly needed, should be an unacceptable limitation.






share|improve this answer























  • Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
    – Deduplicator
    2 days ago












  • @Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
    – max66
    2 days ago






  • 1




    @Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
    – liliscent
    2 days ago















up vote
8
down vote



accepted







up vote
8
down vote



accepted






From cppreference




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 this operator()




In your case, there is nothing that, captured by copy, is modifiable.



I suppose that, if you write something as



int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };


the const should disappear



-- EDIT --



The OP precise




I already knew that adding mutable will solve the issue. The question is that I want to understand the reason behind making the lambda immutable by default.




I'm not a language lawyer but this seems me obvious: if you make operator() not const, you can't make something as



template <typename F>
void foo (F const & f)
{ f(); }

// ...

foo({ std::cout << "lambda!" << std::endl; });


I mean... if operator() isn't const, you can't use lambdas passing they as const reference.



And when isn't strictly needed, should be an unacceptable limitation.






share|improve this answer














From cppreference




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 this operator()




In your case, there is nothing that, captured by copy, is modifiable.



I suppose that, if you write something as



int x = 10;

auto lambda = [=] () mutable { x += 3; return x; };


the const should disappear



-- EDIT --



The OP precise




I already knew that adding mutable will solve the issue. The question is that I want to understand the reason behind making the lambda immutable by default.




I'm not a language lawyer but this seems me obvious: if you make operator() not const, you can't make something as



template <typename F>
void foo (F const & f)
{ f(); }

// ...

foo({ std::cout << "lambda!" << std::endl; });


I mean... if operator() isn't const, you can't use lambdas passing they as const reference.



And when isn't strictly needed, should be an unacceptable limitation.







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 days ago

























answered 2 days ago









max66

32.8k63660




32.8k63660












  • Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
    – Deduplicator
    2 days ago












  • @Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
    – max66
    2 days ago






  • 1




    @Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
    – liliscent
    2 days ago




















  • Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
    – Deduplicator
    2 days ago












  • @Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
    – max66
    2 days ago






  • 1




    @Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
    – liliscent
    2 days ago


















Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
– Deduplicator
2 days ago






Passing a function-object by constant reference is strange. The standard-library (nearly?) always passes callables by value, expecting the caller to employ std::reference_wrapper as needed.
– Deduplicator
2 days ago














@Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
– max66
2 days ago




@Deduplicator - I suppose depends on circumstances. Generally speaking, I don't see a good reason to impose that a callable is modifiable when the called method doens't change the object itself.
– max66
2 days ago




1




1




@Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
– liliscent
2 days ago






@Deduplicator Although passing by value or forwarding-reference is more common, passing const ref isn't really strange. I would think this answer is the reason for the const qualifier of std::function. But for a lambda, it's not convincing, since lambda can certainly be mutable by default, and require a const qualifier for const-ness. () const { ... } looks more consistent to me.
– liliscent
2 days ago














up vote
18
down vote













Found this paper by Herb Sutter at open-std.org which discusses this matter.




The odd couple: Capture by value’s injected const and quirky mutable

Consider this strawman example, where the programmer captures a local variable by value and tries to modify the captured value (which is a member variable of the lambda object):



int val = 0;
auto x = [=]( item e ) // look ma, [=] means explicit copy
{ use( e, ++val ); }; // error: count is const, need ‘mutable’
auto y = [val]( item e ) // darnit, I really can’t get more explicit
{ use( e, ++val ); }; // same error: count is const, need ‘mutable’


This feature appears to have been added out of a concern that the user might not realize he got a copy, and in particular that since lambdas are copyable he might be changing a different lambda’s copy.




The above quote and example indicate why the Standards Committee might have made it const by default and required mutable to change it.






share|improve this answer



















  • 1




    The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
    – ShadowRanger
    2 days ago












  • @ShadowRanger: That's how I understand it. I did not test it though.
    – P.W
    2 days ago















up vote
18
down vote













Found this paper by Herb Sutter at open-std.org which discusses this matter.




The odd couple: Capture by value’s injected const and quirky mutable

Consider this strawman example, where the programmer captures a local variable by value and tries to modify the captured value (which is a member variable of the lambda object):



int val = 0;
auto x = [=]( item e ) // look ma, [=] means explicit copy
{ use( e, ++val ); }; // error: count is const, need ‘mutable’
auto y = [val]( item e ) // darnit, I really can’t get more explicit
{ use( e, ++val ); }; // same error: count is const, need ‘mutable’


This feature appears to have been added out of a concern that the user might not realize he got a copy, and in particular that since lambdas are copyable he might be changing a different lambda’s copy.




The above quote and example indicate why the Standards Committee might have made it const by default and required mutable to change it.






share|improve this answer



















  • 1




    The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
    – ShadowRanger
    2 days ago












  • @ShadowRanger: That's how I understand it. I did not test it though.
    – P.W
    2 days ago













up vote
18
down vote










up vote
18
down vote









Found this paper by Herb Sutter at open-std.org which discusses this matter.




The odd couple: Capture by value’s injected const and quirky mutable

Consider this strawman example, where the programmer captures a local variable by value and tries to modify the captured value (which is a member variable of the lambda object):



int val = 0;
auto x = [=]( item e ) // look ma, [=] means explicit copy
{ use( e, ++val ); }; // error: count is const, need ‘mutable’
auto y = [val]( item e ) // darnit, I really can’t get more explicit
{ use( e, ++val ); }; // same error: count is const, need ‘mutable’


This feature appears to have been added out of a concern that the user might not realize he got a copy, and in particular that since lambdas are copyable he might be changing a different lambda’s copy.




The above quote and example indicate why the Standards Committee might have made it const by default and required mutable to change it.






share|improve this answer














Found this paper by Herb Sutter at open-std.org which discusses this matter.




The odd couple: Capture by value’s injected const and quirky mutable

Consider this strawman example, where the programmer captures a local variable by value and tries to modify the captured value (which is a member variable of the lambda object):



int val = 0;
auto x = [=]( item e ) // look ma, [=] means explicit copy
{ use( e, ++val ); }; // error: count is const, need ‘mutable’
auto y = [val]( item e ) // darnit, I really can’t get more explicit
{ use( e, ++val ); }; // same error: count is const, need ‘mutable’


This feature appears to have been added out of a concern that the user might not realize he got a copy, and in particular that since lambdas are copyable he might be changing a different lambda’s copy.




The above quote and example indicate why the Standards Committee might have made it const by default and required mutable to change it.







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 days ago

























answered 2 days ago









P.W

8,0702439




8,0702439








  • 1




    The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
    – ShadowRanger
    2 days ago












  • @ShadowRanger: That's how I understand it. I did not test it though.
    – P.W
    2 days ago














  • 1




    The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
    – ShadowRanger
    2 days ago












  • @ShadowRanger: That's how I understand it. I did not test it though.
    – P.W
    2 days ago








1




1




The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
– ShadowRanger
2 days ago






The "lambdas are copyable" argument seems a strong one. That would mean that passing the lambda to std::sort, then trying to use it again outside of std::sort (or in a second call to std::sort) wouldn't show any of the changes made by the calls in std::sort, right?
– ShadowRanger
2 days ago














@ShadowRanger: That's how I understand it. I did not test it though.
– P.W
2 days ago




@ShadowRanger: That's how I understand it. I did not test it though.
– P.W
2 days ago










up vote
0
down vote













I think, it is simply to avoid confusion when a variable inside a lambda refer not to what was originally captured. Lexically such a variable is as if in scope of its "original". Copying is mainly to allow to extend the lifetime of object. When a capture is not by copy it refers to original and modifications are applied to the original, and there is no confusion because of two different objects (one of which is implicitly introduced), and it is allowed by lambda's const function call operator.






share|improve this answer








New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • but why I cannot edit my posts??
    – guest
    2 days ago










  • You should be able to. Just click the edit link here.
    – wizzwizz4
    2 days ago










  • "Page Not Found" is the result.
    – guest
    2 days ago










  • Post a bug report on Meta Stack Overflow. That's strange...
    – wizzwizz4
    2 days ago















up vote
0
down vote













I think, it is simply to avoid confusion when a variable inside a lambda refer not to what was originally captured. Lexically such a variable is as if in scope of its "original". Copying is mainly to allow to extend the lifetime of object. When a capture is not by copy it refers to original and modifications are applied to the original, and there is no confusion because of two different objects (one of which is implicitly introduced), and it is allowed by lambda's const function call operator.






share|improve this answer








New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


















  • but why I cannot edit my posts??
    – guest
    2 days ago










  • You should be able to. Just click the edit link here.
    – wizzwizz4
    2 days ago










  • "Page Not Found" is the result.
    – guest
    2 days ago










  • Post a bug report on Meta Stack Overflow. That's strange...
    – wizzwizz4
    2 days ago













up vote
0
down vote










up vote
0
down vote









I think, it is simply to avoid confusion when a variable inside a lambda refer not to what was originally captured. Lexically such a variable is as if in scope of its "original". Copying is mainly to allow to extend the lifetime of object. When a capture is not by copy it refers to original and modifications are applied to the original, and there is no confusion because of two different objects (one of which is implicitly introduced), and it is allowed by lambda's const function call operator.






share|improve this answer








New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









I think, it is simply to avoid confusion when a variable inside a lambda refer not to what was originally captured. Lexically such a variable is as if in scope of its "original". Copying is mainly to allow to extend the lifetime of object. When a capture is not by copy it refers to original and modifications are applied to the original, and there is no confusion because of two different objects (one of which is implicitly introduced), and it is allowed by lambda's const function call operator.







share|improve this answer








New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this answer



share|improve this answer






New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









answered 2 days ago









guest

342




342




New contributor




guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






guest is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • but why I cannot edit my posts??
    – guest
    2 days ago










  • You should be able to. Just click the edit link here.
    – wizzwizz4
    2 days ago










  • "Page Not Found" is the result.
    – guest
    2 days ago










  • Post a bug report on Meta Stack Overflow. That's strange...
    – wizzwizz4
    2 days ago


















  • but why I cannot edit my posts??
    – guest
    2 days ago










  • You should be able to. Just click the edit link here.
    – wizzwizz4
    2 days ago










  • "Page Not Found" is the result.
    – guest
    2 days ago










  • Post a bug report on Meta Stack Overflow. That's strange...
    – wizzwizz4
    2 days ago
















but why I cannot edit my posts??
– guest
2 days ago




but why I cannot edit my posts??
– guest
2 days ago












You should be able to. Just click the edit link here.
– wizzwizz4
2 days ago




You should be able to. Just click the edit link here.
– wizzwizz4
2 days ago












"Page Not Found" is the result.
– guest
2 days ago




"Page Not Found" is the result.
– guest
2 days ago












Post a bug report on Meta Stack Overflow. That's strange...
– wizzwizz4
2 days ago




Post a bug report on Meta Stack Overflow. That's strange...
– wizzwizz4
2 days ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53445857%2fwhy-is-a-lambdas-call-operator-implicitly-const%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?