Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #88145 > unrolled thread
| Started by | Joseph Hesse <joeh@gmail.com> |
|---|---|
| First post | 2022-12-20 11:00 -0600 |
| Last post | 2022-12-22 19:55 +0100 |
| Articles | 10 — 7 participants |
Back to article view | Back to comp.lang.c++
Sum an array in a lambda. Joseph Hesse <joeh@gmail.com> - 2022-12-20 11:00 -0600
Re: Sum an array in a lambda. Öö Tiib <ootiib@hot.ee> - 2022-12-20 09:29 -0800
Re: Sum an array in a lambda. Joseph Hesse <joeh@gmail.com> - 2022-12-21 10:56 -0600
Re: Sum an array in a lambda. Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2022-12-21 10:32 -0800
Re: Sum an array in a lambda. Joseph Hesse <joeh@gmail.com> - 2022-12-22 00:05 -0600
Re: Sum an array in a lambda. Öö Tiib <ootiib@hot.ee> - 2022-12-22 00:00 -0800
Re: Sum an array in a lambda. Ben Bacarisse <ben.usenet@bsb.me.uk> - 2022-12-22 12:42 +0000
Re: Sum an array in a lambda. Paavo Helde <eesnimi@osa.pri.ee> - 2022-12-20 20:03 +0200
Re: Sum an array in a lambda. Juha Nieminen <nospam@thanks.invalid> - 2022-12-21 06:35 +0000
Re: Sum an array in a lambda. Bonita Montero <Bonita.Montero@gmail.com> - 2022-12-22 19:55 +0100
| From | Joseph Hesse <joeh@gmail.com> |
|---|---|
| Date | 2022-12-20 11:00 -0600 |
| Subject | Sum an array in a lambda. |
| Message-ID | <mMCcnTVp9u2wdzz-nZ2dnZfqnPudnZ2d@giganews.com> |
I want to sum an array of int's in a lambda function.
In the following code, function f1 does this with no problem.
In function f2, I am able to sum an int array using a range based
for loop. That this works surprises me since the array name is not
converted to a pointer and the for loop "looks around" to find the
size of int x[].
The commented out code in f2 was my attempt, as in f1, to
put the code to sum the array in a lambda. It does not compile.
Is it possible to make this work?
Thank you,
Joe
=======================================================
#include <iostream>
#include <vector>
using namespace std;
void f1(){
vector<int> v = {1, 2, 3, 4};
auto fp = [] (vector<int> vi)
{
int sum = 0;
for(const int &i : vi)
sum += i;
return sum;
};
cout << "sum = " << fp(v) << '\n';
}
void f2(){
int x[4] = {1, 2, 3, 4};
int sum = 0;
for(const int &i : x)
sum += i;
cout << "sum = " << sum << '\n';
/*
auto fp = [] (int x[])
{
int sum = 0;
for(const int &i : x)
sum += i;
return sum;
};
cout << "sum = " << fp(x) << '\n';
*/
}
int main(){
f1();
f2();
return 0;
}
[toc] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-12-20 09:29 -0800 |
| Message-ID | <99ab1824-5934-428c-a586-0ee640bd5684n@googlegroups.com> |
| In reply to | #88145 |
On Tuesday, 20 December 2022 at 19:00:49 UTC+2, Joseph Hesse wrote: > I want to sum an array of int's in a lambda function. > > In the following code, function f1 does this with no problem. > > In function f2, I am able to sum an int array using a range based > for loop. That this works surprises me since the array name is not > converted to a pointer and the for loop "looks around" to find the > size of int x[]. > > The commented out code in f2 was my attempt, as in f1, to > put the code to sum the array in a lambda. It does not compile. The ... auto fp = [] (int x[]) ... is by language rules equivalent to ... auto fp = [] (int *x) ... so array length information is lost and range based for has no idea what range you mean. > > Is it possible to make this work? Sure, you should either use template ... auto fp = []<size_t N>(int (&x)[N]) ... or you should have fixed array reference ... auto fp = [](int (&x)[4]) ... then the range based for is happy with it.
[toc] | [prev] | [next] | [standalone]
| From | Joseph Hesse <joeh@gmail.com> |
|---|---|
| Date | 2022-12-21 10:56 -0600 |
| Message-ID | <97GdnQ9Gd6Qhpz7-nZ2dnZfqnPudnZ2d@giganews.com> |
| In reply to | #88146 |
On 12/20/22 11:29, Öö Tiib wrote:
> auto fp = [] (int x[])
>
> ... is by language rules equivalent to ...
>
> auto fp = [] (int *x)
>
> ... so array length information is lost and range
> based for has no idea what range you mean.
>
>>
>
In the following program, the array definition and range based for loop
are in the same scope so it appears that the range based for loop sees
the size of the array. The following program compiles with the gnu
compiler and runs correctly. I am surprised that it works.
=========================================
#include <iostream>
#include <vector>
using namespace std;
int main(){
int x[4] = {1, 2, 3, 4};
int sum = 0;
for(const int &i : x)
sum += i;
cout << "sum = " << sum << '\n';
return 0;
}
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2022-12-21 10:32 -0800 |
| Message-ID | <878rj0r4k4.fsf@nosuchdomain.example.com> |
| In reply to | #88198 |
Joseph Hesse <joeh@gmail.com> writes:
> On 12/20/22 11:29, Öö Tiib wrote:
>> auto fp = [] (int x[])
>> ... is by language rules equivalent to ...
>> auto fp = [] (int *x)
>> ... so array length information is lost and range
>> based for has no idea what range you mean.
>>
>>>
>>
> In the following program, the array definition and range based for
> loop are in the same scope so it appears that the range based for loop
> sees the size of the array. The following program compiles with the
> gnu compiler and runs correctly. I am surprised that it works.
> =========================================
> #include <iostream>
> #include <vector>
> using namespace std;
> int main(){
> int x[4] = {1, 2, 3, 4};
> int sum = 0;
> for(const int &i : x)
> sum += i;
> cout << "sum = " << sum << '\n';
> return 0;
> }
Why are you surprised?
In `auto fp = [] (int x[])`, x is an array parameter, which is treated
as a pointer parameter. That equivalence applies only to function
parameters. In your example, you just have an array object.
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Joseph Hesse <joeh@gmail.com> |
|---|---|
| Date | 2022-12-22 00:05 -0600 |
| Message-ID | <6LadnTLge6Mobj7-nZ2dnZfqnPSdnZ2d@giganews.com> |
| In reply to | #88205 |
On 12/21/22 12:32, Keith Thompson wrote:
> Joseph Hesse <joeh@gmail.com> writes:
>> On 12/20/22 11:29, Öö Tiib wrote:
>>> auto fp = [] (int x[])
>>> ... is by language rules equivalent to ...
>>> auto fp = [] (int *x)
>>> ... so array length information is lost and range
>>> based for has no idea what range you mean.
>>>
>>>>
>>>
>> In the following program, the array definition and range based for
>> loop are in the same scope so it appears that the range based for loop
>> sees the size of the array. The following program compiles with the
>> gnu compiler and runs correctly. I am surprised that it works.
>> =========================================
>> #include <iostream>
>> #include <vector>
>> using namespace std;
>> int main(){
>> int x[4] = {1, 2, 3, 4};
>> int sum = 0;
>> for(const int &i : x)
>> sum += i;
>> cout << "sum = " << sum << '\n';
>> return 0;
>> }
>
> Why are you surprised?
>
> In `auto fp = [] (int x[])`, x is an array parameter, which is treated
> as a pointer parameter. That equivalence applies only to function
> parameters. In your example, you just have an array object.
>
In the above program the x in the for loop is treated as
an int *. The fact that the program works means that the
for loop knows how far to increment the pointer to calculate
the sum. This is what surprises me, I thought the only information
a built in array type contains is a pointer to the first element.
Thank you,
Joe
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2022-12-22 00:00 -0800 |
| Message-ID | <e93558ce-937f-4e40-8a7a-a3a6d5ea6855n@googlegroups.com> |
| In reply to | #88212 |
On Thursday, 22 December 2022 at 08:05:59 UTC+2, Joseph Hesse wrote:
> On 12/21/22 12:32, Keith Thompson wrote:
> > Joseph Hesse <jo...@gmail.com> writes:
> >> On 12/20/22 11:29, Öö Tiib wrote:
> >>> auto fp = [] (int x[])
> >>> ... is by language rules equivalent to ...
> >>> auto fp = [] (int *x)
> >>> ... so array length information is lost and range
> >>> based for has no idea what range you mean.
> >>>
> >>>>
> >>>
> >> In the following program, the array definition and range based for
> >> loop are in the same scope so it appears that the range based for loop
> >> sees the size of the array. The following program compiles with the
> >> gnu compiler and runs correctly. I am surprised that it works.
> >> =========================================
> >> #include <iostream>
> >> #include <vector>
> >> using namespace std;
> >> int main(){
> >> int x[4] = {1, 2, 3, 4};
> >> int sum = 0;
> >> for(const int &i : x)
> >> sum += i;
> >> cout << "sum = " << sum << '\n';
> >> return 0;
> >> }
> >
> > Why are you surprised?
> >
> > In `auto fp = [] (int x[])`, x is an array parameter, which is treated
> > as a pointer parameter. That equivalence applies only to function
> > parameters. In your example, you just have an array object.
> >
> In the above program the x in the for loop is treated as
> an int *. The fact that the program works means that the
> for loop knows how far to increment the pointer to calculate
> the sum. This is what surprises me, I thought the only information
> a built in array type contains is a pointer to the first element.
>
That is not true. The x in that program is int array of 4 elements,
not pointer. The array decays to pointer in lot of contexts but
range based for is not one of those. It treats x as an array.
<https://en.cppreference.com/w/cpp/language/range-for>
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2022-12-22 12:42 +0000 |
| Message-ID | <87lemzsj7e.fsf@bsb.me.uk> |
| In reply to | #88214 |
Öö Tiib <ootiib@hot.ee> writes:
> On Thursday, 22 December 2022 at 08:05:59 UTC+2, Joseph Hesse wrote:
>> On 12/21/22 12:32, Keith Thompson wrote:
>> > Joseph Hesse <jo...@gmail.com> writes:
>> >> On 12/20/22 11:29, Öö Tiib wrote:
>> >>> auto fp = [] (int x[])
>> >>> ... is by language rules equivalent to ...
>> >>> auto fp = [] (int *x)
>> >>> ... so array length information is lost and range
>> >>> based for has no idea what range you mean.
>> >>>
>> >>>>
>> >>>
>> >> In the following program, the array definition and range based for
>> >> loop are in the same scope so it appears that the range based for loop
>> >> sees the size of the array. The following program compiles with the
>> >> gnu compiler and runs correctly. I am surprised that it works.
>> >> =========================================
>> >> #include <iostream>
>> >> #include <vector>
>> >> using namespace std;
>> >> int main(){
>> >> int x[4] = {1, 2, 3, 4};
>> >> int sum = 0;
>> >> for(const int &i : x)
>> >> sum += i;
>> >> cout << "sum = " << sum << '\n';
>> >> return 0;
>> >> }
>> >
>> > Why are you surprised?
>> >
>> > In `auto fp = [] (int x[])`, x is an array parameter, which is treated
>> > as a pointer parameter. That equivalence applies only to function
>> > parameters. In your example, you just have an array object.
>> >
>> In the above program the x in the for loop is treated as
>> an int *. The fact that the program works means that the
>> for loop knows how far to increment the pointer to calculate
>> the sum. This is what surprises me, I thought the only information
>> a built in array type contains is a pointer to the first element.
>>
> That is not true. The x in that program is int array of 4 elements,
> not pointer. The array decays to pointer in lot of contexts but
> range based for is not one of those. It treats x as an array.
> <https://en.cppreference.com/w/cpp/language/range-for>
You are right (of course!) but it's by no means trivial to follow the
details. The cppreference page gives an example, but it's explanation
is very hard to plough through for someone learning C++. You'd have to
understand how
auto&& __range = x;
works and what __range and __range + 4 mean following a declaration like
that.
Clearly (at least I think so) __range will be an rvalue reference to an
array of 4 ints, but when I try to ditch the auto with
int (&&__range)[4] = x;
g++ complains that it "cannot bind rvalue reference of type ‘int
(&&)[4]’ to lvalue of type ‘int [4]’. What is the type that is being
deduced for __range in
auto&& __range = x;
? (Using a lvalue reference works but that's not what the standard says
is going on with this range-based for statement.)
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Paavo Helde <eesnimi@osa.pri.ee> |
|---|---|
| Date | 2022-12-20 20:03 +0200 |
| Message-ID | <tnstee$oct8$1@dont-email.me> |
| In reply to | #88145 |
20.12.2022 19:00 Joseph Hesse kirjutas:
> I want to sum an array of int's in a lambda function.
>
> In the following code, function f1 does this with no problem.
>
> In function f2, I am able to sum an int array using a range based
> for loop. That this works surprises me since the array name is not
> converted to a pointer and the for loop "looks around" to find the
> size of int x[].
>
> The commented out code in f2 was my attempt, as in f1, to
> put the code to sum the array in a lambda. It does not compile.
>
> Is it possible to make this work?
>
> Thank you,
> Joe
> =======================================================
> #include <iostream>
> #include <vector>
> using namespace std;
>
> void f2(){
> int x[4] = {1, 2, 3, 4};
>
> int sum = 0;
> for(const int &i : x)
> sum += i;
> cout << "sum = " << sum << '\n';
>
> /*
> auto fp = [] (int x[])
> {
> int sum = 0;
> for(const int &i : x)
> sum += i;
> return sum;
> };
>
> cout << "sum = " << fp(x) << '\n';
> */
> }
You can fix it easily by over-using auto:
void f2() {
int x[4] = { 1, 2, 3, 4 };
auto fp = [] (const auto& x)
{
int sum = 0;
for(const int &i : x)
sum += i;
return sum;
};
std::cout << "sum = " << fp(x) << '\n';
}
However, using C arrays seems fragile in general as they decay to
pointers too easily. This seems better:
void f2() {
std::array<int, 4> x = { 1, 2, 3, 4 };
auto fp = [] (const auto& range)
{
int sum = 0;
for(const int &i : range)
sum += i;
return sum;
};
std::cout << "sum = " << fp(x) << '\n';
}
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-12-21 06:35 +0000 |
| Message-ID | <tnu9f7$vn7$1@gioia.aioe.org> |
| In reply to | #88145 |
Joseph Hesse <joeh@gmail.com> wrote: > auto fp = [] (vector<int> vi) By the way, you should almost never take class instances like this as function parameters by value. You should almost always take them as const reference. When you take it by value like that, it will be *copied* for the function. The larger the vector is, the heavier it becomes to copy. In most cases (like here) the function doesn't need a copy of the vector. A reference to the original suffices (and passing a reference as parameter to the function is infinitely more efficient than copying the entire vector). The only case where you want to pass such an object by value instead of by reference is when the function actually needs a deep-copy of the object, but that's quite rare. (Even in such cases it's actually usually better to still take the parameter by const reference and copy it inside the function.)
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2022-12-22 19:55 +0100 |
| Message-ID | <to295e$1ekd5$1@dont-email.me> |
| In reply to | #88145 |
Am 20.12.2022 um 18:00 schrieb Joseph Hesse: > cout << "sum = " << fp(v) << '\n'; cout << "sum = " << accumulate( v.cbegin(), v.cend() ) << endl;
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web