lambda capture: types should decay when objects are captured by value

114 views
Skip to first unread message

victor.kh...@gmail.com

unread,
Jul 29, 2018, 4:01:30 PM7/29/18
to ISO C++ Standard - Discussion
Consider:

  const int a=1;
  auto f=[a]() mutable { ++a; } // error: the type of closure's member is const int
  int a_copy=a;
  auto f=[a_copy]() mutable { ++a_copy; } // OK now

So copying an object is different from copying a copy of an object, which seems wrong.

From cppreference: The type of each data member is the type of the corresponding captured entity, except if the entity has reference type (in that case, references to functions are captured as lvalue references to the referenced functions, and references to objects are captured as copies of the referenced objects).

I think this should be changed to the decayed types.

Any opinions?

Victor.


Richard Hodges

unread,
Jul 29, 2018, 6:44:04 PM7/29/18
to std-dis...@isocpp.org
FWIW I agree with you, since this is fine:

auto f=[a=a]() mutable { ++a; }; // ok

And it seems to me that it should do exactly the same thing.


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

Brian Bi

unread,
Jul 30, 2018, 5:37:20 PM7/30/18
to std-dis...@isocpp.org
I sort of agree, but this change would make the type of a depend on whether it's being odr-used or not (note that non-odr-uses of a refer to the enclosing entity, not the captured value), which seems unfortunate. Since in C++14 we have the workaround posted by Richard, perhaps it's best to just let this be.

On Sun, Jul 29, 2018 at 3:43 PM, Richard Hodges <hodg...@gmail.com> wrote:
FWIW I agree with you, since this is fine:

auto f=[a=a]() mutable { ++a; }; // ok

And it seems to me that it should do exactly the same thing.

On Sun, 29 Jul 2018 at 22:01, <victor.kh...@gmail.com> wrote:
Consider:

  const int a=1;
  auto f=[a]() mutable { ++a; } // error: the type of closure's member is const int
  int a_copy=a;
  auto f=[a_copy]() mutable { ++a_copy; } // OK now

So copying an object is different from copying a copy of an object, which seems wrong.

From cppreference: The type of each data member is the type of the corresponding captured entity, except if the entity has reference type (in that case, references to functions are captured as lvalue references to the referenced functions, and references to objects are captured as copies of the referenced objects).

I think this should be changed to the decayed types.

Any opinions?

Victor.


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.

To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.

To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi

Richard Hodges

unread,
Jul 30, 2018, 6:40:46 PM7/30/18
to std-dis...@isocpp.org
On Mon, 30 Jul 2018 at 23:37, Brian Bi <bbi...@gmail.com> wrote:
I sort of agree, but this change would make the type of a depend on whether it's being odr-used or not (note that non-odr-uses of a refer to the enclosing entity, not the captured value), which seems unfortunate. Since in C++14 we have the workaround posted by Richard, perhaps it's best to just let this be.

Without wishing to be controversial, I strongly feel that this is exactly the kind of thinking that will ensure that c++ remains firmly sidelined as a language choice for new projects.

There is no plausible case where a programmer would wish to capture a const copy in a mutable lambda. Regardless of the wording of the spec. It's simply illogical.

This is a bug in the spec and the language, pure and simple. It just needs to be fixed so we can all move on.

Continual pandering to the myth of backward compatibility for its own sake is the root of every single one of c++'s problems today.

I for one value correctness over compatibility with incorrect programs. So do the users of every other language.


On Sun, Jul 29, 2018 at 3:43 PM, Richard Hodges <hodg...@gmail.com> wrote:
FWIW I agree with you, since this is fine:

auto f=[a=a]() mutable { ++a; }; // ok

And it seems to me that it should do exactly the same thing.

On Sun, 29 Jul 2018 at 22:01, <victor.kh...@gmail.com> wrote:
Consider:

  const int a=1;
  auto f=[a]() mutable { ++a; } // error: the type of closure's member is const int
  int a_copy=a;
  auto f=[a_copy]() mutable { ++a_copy; } // OK now

So copying an object is different from copying a copy of an object, which seems wrong.

From cppreference: The type of each data member is the type of the corresponding captured entity, except if the entity has reference type (in that case, references to functions are captured as lvalue references to the referenced functions, and references to objects are captured as copies of the referenced objects).

I think this should be changed to the decayed types.

Any opinions?

Victor.


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.

To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.

To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.

Ville Voutilainen

unread,
Jul 30, 2018, 7:04:18 PM7/30/18
to std-dis...@isocpp.org
On 31 July 2018 at 01:40, Richard Hodges <hodg...@gmail.com> wrote:
> There is no plausible case where a programmer would wish to capture a const
> copy in a mutable lambda. Regardless of the wording of the spec. It's simply
> illogical.

Such plausible cases have been explained before when this matter has come up.
Transformation from a loop to an algorithm that uses a lambda was the
original motivation.

> This is a bug in the spec and the language, pure and simple. It just needs
> to be fixed so we can all move on.

It's not a bug, the spec is as intended by the original lambda design.

Tam S. B.

unread,
Jul 31, 2018, 6:42:35 AM7/31/18
to std-dis...@isocpp.org
Current rule allows

const int length = 42;
[=]() mutable { int array[length]; };

The proposed rule will make that either invalid or extra tricky.

________________________________________
From: victor.kh...@gmail.com <victor.kh...@gmail.com>
Sent: Sunday, July 29, 2018 8:01:30 PM
To: ISO C++ Standard - Discussion
Subject: [std-discussion] lambda capture: types should decay when objects are captured by value
--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org<mailto:std-discussio...@isocpp.org>.
To post to this group, send email to std-dis...@isocpp.org<mailto:std-dis...@isocpp.org>.

Richard Hodges

unread,
Jul 31, 2018, 7:21:31 AM7/31/18
to std-dis...@isocpp.org
On Tue, 31 Jul 2018 at 12:42, Tam S. B. <cpple...@outlook.com> wrote:
Current rule allows

  const int length = 42;
  [=]() mutable { int array[length]; };

The proposed rule will make that either invalid or extra tricky.

c++ already has a mechanism for this if desired - the superior constexpr:

  constexpr int length = 42;

  [=]() mutable { int array[length]; };

The given example stops working without compiler extensions in the general case:

  const int length = get_value();
  [=]() mutable { int array[length]; /* requires nonstandard compiler extension - 
therefore not a motivation for a language rule */ };


 
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.

Ville Voutilainen

unread,
Jul 31, 2018, 7:27:02 AM7/31/18
to std-dis...@isocpp.org
On 31 July 2018 at 14:21, Richard Hodges <hodg...@gmail.com> wrote:
>
>
> On Tue, 31 Jul 2018 at 12:42, Tam S. B. <cpple...@outlook.com> wrote:
>>
>> Current rule allows
>>
>> const int length = 42;
>> [=]() mutable { int array[length]; };
>>
>> The proposed rule will make that either invalid or extra tricky.
>
>
> c++ already has a mechanism for this if desired - the superior constexpr:

The initialization of a const int from a constant uses that very mechanism.

> constexpr int length = 42;
> [=]() mutable { int array[length]; };
>
> The given example stops working without compiler extensions in the general
> case:
>
> const int length = get_value();
> [=]() mutable { int array[length]; /* requires nonstandard compiler
> extension - therefore not a motivation for a language rule */ };

If get_value produces a constant expression, that works just fine
without any extensions.

Richard Hodges

unread,
Jul 31, 2018, 8:16:24 AM7/31/18
to std-dis...@isocpp.org
As it would with constexpr, but with constexpr it would be clearer and not vulnerable to misinterpretation.

We would get equivalent functionality on request plus logical functionality in the general case.

i.e. better.

Victor Khomenko

unread,
Jul 31, 2018, 9:05:00 AM7/31/18
to std-dis...@isocpp.org
That should really be constexpr, and one then wouldn't even have to capture it. So not really extra tricky.

The usage of const you suggested is actually confusing, e.g. consider

void f(const int length=42){...}




You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-discussion/FAb7nRfmU3I/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.

T. C.

unread,
Aug 1, 2018, 6:21:50 PM8/1/18
to ISO C++ Standard - Discussion
The really confusing example is

constexpr int length = 42;
[=]() mutable {
  length = 9000; // odr-use, modifies captured member
  int m[length]; // not odr-use, so refers to 'length' from surrounding scope; m is a int[42]
};

Liu Hao

unread,
Aug 2, 2018, 3:16:23 AM8/2/18
to std-dis...@isocpp.org, T. C.
在 2018-08-02 06:21, T. C. 写道:
> The really confusing example is
>
> constexpr int length = 42;
> [=]() mutable {
>   length = 9000; // odr-use, modifies captured member
>   int m[length]; // not odr-use, so refers to 'length' from surrounding
> scope; m is a int[42]
> };
>

Why don't we just make `constexpr` objects have static storage duration,
so they can't be captured at all?


--
Best regards,
ltpmouse
Reply all
Reply to author
Forward
0 new messages