user3852441 February 2016

Replace 'for loop' using std::for_each

I have a for loop in the below code and I would like to implement it using std::for_each. I have implemented it. Could someone please tell me if that is the best way to do it using std::for_each? If not, could you please suggest the right one?

#include <vector>
#include <cstdint>
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>

int main()
{
    std::vector<std::uint32_t> nums{3, 4, 2, 8, 15};
    std::stringstream list1;


    for (auto n : nums)
    {
        list1 << n<<",";
    }

    //Is this the right way to do using std::for_each so that above for loop can be done in 1 line??
    std::for_each(nums.begin(),nums.end(),[&list1](std::uint32_t n){ list1 << n << ","; });

}

Answers


Milica February 2016

Yes, that is right. There is no need for the reference in (std::uint32_t &n) if you had performance as the motive.


Simon Kraemer February 2016

Why don't you just test it out?

auto vs std::for_each

As you can see the assembly output is the same for both. It just doesn't make any difference for your example.


NathanOliver February 2016

If you want to copy the data from one thing to another you can use std::copy

int main()
{
    std::vector<std::uint32_t> nums{3, 4, 2, 8, 15};
    std::stringstream list1;

    std::copy(nums.begin(), nums.end(),std::ostream_iterator<std::uint32_t>(list1,","));
    std::cout << list1.str();
}

Live Example

This will end the stream with a , but that is the same thing you get in you code.

If you do not want this then you should look at Pretty-print C++ STL containers


Jerry Coffin February 2016

Yes, your use of for_each is a reasonable analog of the preceding loop.

I feel obliged to point out, however, that I find for_each probably the least useful algorithm in the library. From what I've seen, using it generally indicates that you're still basically thinking in terms of loops, and just changing the syntax you use for those loops. I also think that range-based for loops have probably eliminated at least 90% of the (already few) legitimate uses there used to be for for_each.

In this case, your code is really imitating using std::copy with an std::ostream_iterator:

std::copy(nums.begin(), nums.end(), 
          std::ostream_iterator<std::uint32_t>(std::cout, ","));

Even this, however, is clumsy enough that I think it's open to question whether it's really an improvement over a range-based for loop.

Post Status

Asked in February 2016
Viewed 1,565 times
Voted 11
Answered 4 times

Search




Leave an answer