for_each with vector of function objects

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • alan.patterson5@gmail.com

    #1

    for_each with vector of function objects

    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<intx (values.begin() , values.end());

    vector<functorf uncs;
    // 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[i](x[i]);
    }

  • Pete Becker

    #2
    Re: for_each with vector of function objects

    alan.patterson5 @gmail.com 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<intx (values.begin() , values.end());
    >
    vector<functorf uncs;
    // 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[i](x[i]);
    }
    >
    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++)(*fi rst2++);
    }

    and you'd call it like this:

    apply(funcs.beg in(), 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.beg in(), 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)

    Comment

    • Daniel T.

      #3
      Re: for_each with vector of function objects

      In article <1163518005.185 341.257680@h48g 2000cwc.googleg roups.com>,
      alan.patterson5 @gmail.com 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<intx (values.begin() , values.end());
      >
      vector<functorf uncs;
      // 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[i](x[i]);
      }
      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.

      Comment

      • Earl Purple

        #4
        Re: for_each with vector of function objects


        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++)(*fi rst2++);
        }
        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)(*firs t2);
        ++first1;
        ++first2;
        }
        }
        and you'd call it like this:
        >
        apply(funcs.beg in(), funcs.end(), x.begin(), x.end());
        In my example no x.end(), just the first 3 parameters.

        Comment

        • Earl Purple

          #5
          Re: for_each with vector of function objects


          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 );
          }

          Comment

          • alan.patterson5@gmail.com

            #6
            Re: for_each with vector of function objects

            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." <danie...@earth link.netwrote:
            In article <1163518005.185 341.257...@h48g 2000cwc.googleg roups.com>,
            >
            >
            >
            alan.patters... @gmail.com 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<intx (values.begin() , values.end());
            >
            vector<functorf uncs;
            // 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[i](x[i]);
            }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.

            Comment

            • Pete Becker

              #7
              Re: for_each with vector of function objects

              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++)(*fi rst2++);
              >}
              >
              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)(*firs t2);
              ++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)

              Comment

              Working...