9

for_each accepts InputIterators :

//from c++ standard
template <class InputIterator, class Function>
   Function for_each (InputIterator first, InputIterator last, Function f);

is it ok to change the object in Function f, like this :

struct AddOne
{
    void operator()(int & x){x = x + 1;}
};

std::vector<int> vec(10);
std::for_each(vec.begin(),vec.end(),AddOne());

This code works in VC++2008 and also with GCC, but is it also portable (legal) code ?
(InputIterators are only guaranteed to be usable as rvalue, in this case they are used as lvalue in AddOne's operator())

qwerty
  • 373
  • 2
  • 8

5 Answers5

8

Read this article.

To be pedantic: for_each is a non-modifying sequence operation. The intent is not to modify the sequence. However, it is okay to modify the input sequence when using for_each.

dirkgently
  • 108,024
  • 16
  • 131
  • 187
4

You misunderstand something. Saying input iterators are only guaranteed to be usable as rvalues doesn't mean you can't get an lvalue out of an iterator somehow. So it does not mean that the result of *iterator is an rvalue. What you/for_each passes to AddOne is the result of operator* - not the iterator itself.

About for_each and a modifying function object - read this question

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
3

If in doubt use std::transform as it will convey even to the casual reader of your code that you intend to modify something.

lothar
  • 19,853
  • 5
  • 45
  • 59
2

It is legal - the input iterators are used to specify the range, not to do the processing.

Interestingly, Josuttis in his book "The C++ Standard Library" lists for_each as modifying, raher than non-modifying.

0

My suggestion would be, it all matters how you pass your item to the function i.e. whether by reference or pointer and change it or as a copy and change it.

But as other's have said, if you want to change the values, it's better to use transform as it cares about the return values.

    class MultiplyBy {
    private:
        int factor;

    public:
        MultiplyBy(int x) : factor(x) {
        }

        int operator () (int other) const {
            other = factor + other;
            return other; 
          } 

    //  int operator () (int & other) const { 
    //         other = factor + other;
    //         return other;        
    //     }      
    };

        vector<int> x1= {1, 2, 3, 4, 5};
        vector<int> x2;   
        std::transform(x1.begin(), x1.end(), back_inserter(x2), MultiplyBy(3));
        std::for_each(x1.begin(), x1.end(), MultiplyBy(3));  
Kumar Roshan Mehta
  • 3,078
  • 2
  • 27
  • 50