By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,344 Members | 1,853 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,344 IT Pros & Developers. It's quick & easy.

for_each with vector of function objects

P: n/a
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<functorfuncs;
// 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]);
}

Nov 14 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
al*************@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<functorfuncs;
// 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++)(*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)
Nov 14 '06 #2

P: n/a
In article <11**********************@h48g2000cwc.googlegroups .com>,
al*************@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<functorfuncs;
// 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.
Nov 14 '06 #3

P: n/a

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.

Nov 14 '06 #4

P: n/a

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

Nov 14 '06 #5

P: n/a
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...@earthlink.netwrote:
In article <1163518005.185341.257...@h48g2000cwc.googlegroups .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<functorfuncs;
// 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.
Nov 14 '06 #6

P: n/a
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)
Nov 14 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.