for_each with vector of function objects

Discussion in 'C++' started by alan.patterson5@gmail.com, Nov 14, 2006.

  1. Guest

    I have a vector of N values and a vector of N functors. I want to apply
    each functor to its corresponding value. What would be the 'correct'
    STL way to do this.
    for_each takes on functor and applies it to every element.
    So presumably transform is a better option but it also takes one
    functor.
    This is obviously easily solved by a variety of methods but I am
    interested in how the STL would best solve this problem.
    e.g.

    // fill vector with some values
    vector<int> x (values.begin(), values.end());

    vector<functor> funcs;
    // fill funcs with different functors, or functors with different
    parameters

    // would like to do STL equivalent of
    for (int i=0; i<x.size(); ++i) {
    funcs(x);
    }
    , Nov 14, 2006
    #1
    1. Advertising

  2. Pete Becker Guest

    wrote:
    > I have a vector of N values and a vector of N functors. I want to apply
    > each functor to its corresponding value. What would be the 'correct'
    > STL way to do this.
    > for_each takes on functor and applies it to every element.
    > So presumably transform is a better option but it also takes one
    > functor.
    > This is obviously easily solved by a variety of methods but I am
    > interested in how the STL would best solve this problem.
    > e.g.
    >
    > // fill vector with some values
    > vector<int> x (values.begin(), values.end());
    >
    > vector<functor> funcs;
    > // fill funcs with different functors, or functors with different
    > parameters
    >
    > // would like to do STL equivalent of
    > for (int i=0; i<x.size(); ++i) {
    > funcs(x);
    > }
    >


    I'd write the explicit loop. But if you want to write a template that
    takes iterators, it would be something like this:

    template <class Iter1, class Iter2>
    void apply(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)
    {
    while (first1 != last1 && first2 != last2)
    (*first1++)(*first2++);
    }

    and you'd call it like this:

    apply(funcs.begin(), funcs.end(), x.begin(), x.end());

    Or, if the only reason you copied values in the first place was to get
    the contents into a vector, you can skip that copy and pass the values
    iterators:

    apply(funcs.begin(), funcs.end(), values.begin(), values.end());

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
    Pete Becker, Nov 14, 2006
    #2
    1. Advertising

  3. Daniel T. Guest

    In article <>,
    wrote:

    > I have a vector of N values and a vector of N functors. I want to apply
    > each functor to its corresponding value. What would be the 'correct'
    > STL way to do this.
    > for_each takes on functor and applies it to every element.
    > So presumably transform is a better option but it also takes one
    > functor.
    > This is obviously easily solved by a variety of methods but I am
    > interested in how the STL would best solve this problem.
    > e.g.
    >
    > // fill vector with some values
    > vector<int> x (values.begin(), values.end());
    >
    > vector<functor> funcs;
    > // fill funcs with different functors, or functors with different
    > parameters
    >
    > // would like to do STL equivalent of
    > for (int i=0; i<x.size(); ++i) {
    > funcs(x);
    > }


    There is a transform that takes iterators into two containers, but it
    assumes that the functions will produce outputs and you don't seem to be
    doing that. As such, I agree with Pete's post.

    --
    To send me email, put "sheltie" in the subject.
    Daniel T., Nov 14, 2006
    #3
  4. Earl Purple Guest

    Pete Becker wrote:
    > I'd write the explicit loop. But if you want to write a template that
    > takes iterators, it would be something like this:
    >
    > template <class Iter1, class Iter2>
    > void apply(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)
    > {
    > while (first1 != last1 && first2 != last2)
    > (*first1++)(*first2++);
    > }


    Do you need to increment both? transform that takes 2 inputs only
    increments one and relies on "UB" if the unchecked sequence is shorter
    than the first. (It can be longer, it simply runs for the length of the
    checked sequence).

    Also although it can be written in one line, I think it's better to use
    pre-increment because it avoids a copy of the iterator, and you don't
    know how expensive that might be from a template. Although it is more
    lines in your code, I don't see that it will generate more lines of
    object code. So how about:

    template< typename Iter1, typename Iter2 >
    void apply( Iter1 first1, Iter1 last1, Iter2 first2 )
    {
    while ( first1 != last1 )
    {
    (*first1)(*first2);
    ++first1;
    ++first2;
    }
    }

    > and you'd call it like this:
    >
    > apply(funcs.begin(), funcs.end(), x.begin(), x.end());


    In my example no x.end(), just the first 3 parameters.
    Earl Purple, Nov 14, 2006
    #4
  5. Earl Purple Guest

    Daniel T. wrote:
    >
    > There is a transform that takes iterators into two containers, but it
    > assumes that the functions will produce outputs and you don't seem to be
    > doing that. As such, I agree with Pete's post.


    To use that you'd have to write a non-iterator for the output, and the
    operator that takes the 2 parameters would get the functor to invoke on
    the object. Easier to write the algorithm, but if we really want to use
    transform:

    iterator: all of the operators (++, *, =) will do nothing. operator=()
    could be a template because it does nothing with its parameter anyway.
    Not sure what you'd do with the typedefs if we really need them anyway.

    operator:

    struct call_func
    {
    template < typename F, typename P >
    void operator() ( F func, P param )
    {
    func( param );
    }
    };

    The final way is to use for_each and get the functor to store the
    beginning of one sequence. Let's say it stores the functors. Again it
    could store an iterator.

    template < typename FuncIterator >
    struct FunctorFunctor
    {
    private:
    FuncIterator func_iter;

    public:
    explicit FunctorFunctor( FuncIterator fi ) : func_iter ( fi ) {}

    template < typename T >
    void operator() ( T t )
    {
    (*func_iter)( t );
    ++func_iter;
    }
    };

    template< typename FuncIterator >
    FunctorFunctor< FuncIterator > functor_functor( FuncIterator fi )
    {
    return FunctorFunctor< FuncIterator >( fi );
    }
    Earl Purple, Nov 14, 2006
    #5
  6. Guest

    Ok, the solution is to write my own STL like function. I like the apply
    idea.

    If I were to return values from the function and store these in a
    result vector then I could use transform a la:

    transform (values.begin(), values.end(), functors.begin(),
    results.begin(), my_apply());

    where:

    struct my_apply
    {
    template< typename T, typename F >
    T operator()(T& x, F& f) {
    return f(x);
    }
    };

    Does this work with boost::lambda?

    transform (values.begin(), values.end(), functors.begin(),
    results.begin(), _2(_1) );

    Thanks,
    Alan
    On Nov 14, 4:00 pm, "Daniel T." <> wrote:
    > In article <>,
    >
    >
    >
    > wrote:
    > > I have a vector of N values and a vector of N functors. I want to apply
    > > each functor to its corresponding value. What would be the 'correct'
    > > STL way to do this.
    > > for_each takes on functor and applies it to every element.
    > > So presumably transform is a better option but it also takes one
    > > functor.
    > > This is obviously easily solved by a variety of methods but I am
    > > interested in how the STL would best solve this problem.
    > > e.g.

    >
    > > // fill vector with some values
    > > vector<int> x (values.begin(), values.end());

    >
    > > vector<functor> funcs;
    > > // fill funcs with different functors, or functors with different
    > > parameters

    >
    > > // would like to do STL equivalent of
    > > for (int i=0; i<x.size(); ++i) {
    > > funcs(x);
    > > }There is a transform that takes iterators into two containers, but it

    > assumes that the functions will produce outputs and you don't seem to be
    > doing that. As such, I agree with Pete's post.
    >
    > --
    > To send me email, put "sheltie" in the subject.
    , Nov 14, 2006
    #6
  7. Pete Becker Guest

    Earl Purple wrote:
    > Pete Becker wrote:
    >> I'd write the explicit loop. But if you want to write a template that
    >> takes iterators, it would be something like this:
    >>
    >> template <class Iter1, class Iter2>
    >> void apply(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2)
    >> {
    >> while (first1 != last1 && first2 != last2)
    >> (*first1++)(*first2++);
    >> }

    >
    > Do you need to increment both?


    Yes, you need to increment both. If you like, you can skip the second
    comparison, but the information is there, so why not use it?

    > transform that takes 2 inputs only
    > increments one and relies on "UB" if the unchecked sequence is shorter
    > than the first.


    It doesn't rely on UB. In fact, I'm not even sure what that means. It
    says that the behavior is undefined if the second sequence is too short.

    >
    > Also although it can be written in one line, I think it's better to use
    > pre-increment because it avoids a copy of the iterator, and you don't
    > know how expensive that might be from a template. Although it is more
    > lines in your code, I don't see that it will generate more lines of
    > object code. So how about:
    >
    > template< typename Iter1, typename Iter2 >
    > void apply( Iter1 first1, Iter1 last1, Iter2 first2 )
    > {
    > while ( first1 != last1 )
    > {
    > (*first1)(*first2);
    > ++first1;
    > ++first2;
    > }
    > }
    >


    Write it however you like.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
    Pete Becker, Nov 14, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Black
    Replies:
    18
    Views:
    698
    Daniel T.
    Jun 16, 2004
  2. Replies:
    8
    Views:
    544
    PJP of NYC
    May 24, 2005
  3. Replies:
    8
    Views:
    1,893
    Csaba
    Feb 18, 2006
  4. PolkaHead
    Replies:
    3
    Views:
    460
    Daniel T.
    Nov 29, 2006
  5. Chris Roth

    Vector reserve in a for_each

    Chris Roth, Feb 24, 2007, in forum: C++
    Replies:
    9
    Views:
    403
    Rolf Magnus
    Mar 2, 2007
Loading...

Share This Page