L
Leslie Sanford
I need an interative form of the std::transform algorithm. In other words,
instead of letting transform do its work and accessing the results
afterwards, I need to access each transformation as it occurs. The reason is
that if I rely solely on std::transform, I would have to make several calls
to it storing the results in buffers. While this would look nice, it implies
a lot of looping in the background. So I've written a
"BinaryTransformIterator." The idea is to run several of these iterators in
one loop, manipulating and combining the results as I go along. The hope is
that this will make my code more concise. However, at this point this
exercise is more of an experiment; I'm just playing around at present. I'm
not sure yet if it's useful.
At any rate, I'm hoping for comments and about the correctness of the code
and any suggestions for improving it.
template<typename InputIterator1,
typename InputIterator2,
typename BinaryFunction>
class BinaryTransformIterator :
public std::iterator<std::input_iterator_tag,
typename BinaryFunction::result_type>
{
private:
typedef BinaryTransformIterator<InputIterator1,
InputIterator2,
BinaryFunction> self;
InputIterator1 myFirst1;
InputIterator1 myLast1;
InputIterator2 myFirst2;
BinaryFunction myFunction;
value_type result;
public:
BinaryTransformIterator()
{
myFirst1 = myLast1;
}
BinaryTransformIterator(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
BinaryFunction function = BinaryFunction()) :
myFirst1(first1),
myLast1(last1),
myFirst2(first2),
myFunction(function)
{
if(!IsDone())
{
result = myFunction(*myFirst1, *myFirst2);
}
}
bool operator==(const self &other)
{
return this->IsDone() == other.IsDone() ? true :
(this->myFirst1 == other.myFirst1) &&
(this->myLast1 == other.myLast1) &&
(this->myFirst2 == other.myFirst2);
}
bool operator!=(const self &other)
{
return !(*this == other);
}
value_type operator*()
{
assert(!IsDone());
return result;
}
self &operator++()
{
assert(!IsDone());
++myFirst1;
++myFirst2;
if(!IsDone())
{
result = myFunction(*myFirst1, *myFirst2);
}
return *this;
}
self operator++(int)
{
assert(!IsDone());
self temp = *this;
++myFirst1;
++myFirst2;
if(!IsDone())
{
result = myFunction(*myFirst1, *myFirst2);
}
return temp;
}
private:
bool IsDone() const
{
return myFirst1 == myLast1;
}
};
// TEST
typedef BinaryTransformIterator<float *, float *, std::multiplies<float> >
iterator;
int main(void)
{
float buffer1[] = { 1, 2, 3, 4, 5 };
float buffer2[] = { 2, 2, 2, 2, 2 };
iterator first(&buffer1[0], &buffer1[5], buffer2);
iterator last;
for(int i = 0; first != last; i++)
{
assert(*first == buffer1 * buffer2);
++first;
}
return 0;
}
instead of letting transform do its work and accessing the results
afterwards, I need to access each transformation as it occurs. The reason is
that if I rely solely on std::transform, I would have to make several calls
to it storing the results in buffers. While this would look nice, it implies
a lot of looping in the background. So I've written a
"BinaryTransformIterator." The idea is to run several of these iterators in
one loop, manipulating and combining the results as I go along. The hope is
that this will make my code more concise. However, at this point this
exercise is more of an experiment; I'm just playing around at present. I'm
not sure yet if it's useful.
At any rate, I'm hoping for comments and about the correctness of the code
and any suggestions for improving it.
template<typename InputIterator1,
typename InputIterator2,
typename BinaryFunction>
class BinaryTransformIterator :
public std::iterator<std::input_iterator_tag,
typename BinaryFunction::result_type>
{
private:
typedef BinaryTransformIterator<InputIterator1,
InputIterator2,
BinaryFunction> self;
InputIterator1 myFirst1;
InputIterator1 myLast1;
InputIterator2 myFirst2;
BinaryFunction myFunction;
value_type result;
public:
BinaryTransformIterator()
{
myFirst1 = myLast1;
}
BinaryTransformIterator(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
BinaryFunction function = BinaryFunction()) :
myFirst1(first1),
myLast1(last1),
myFirst2(first2),
myFunction(function)
{
if(!IsDone())
{
result = myFunction(*myFirst1, *myFirst2);
}
}
bool operator==(const self &other)
{
return this->IsDone() == other.IsDone() ? true :
(this->myFirst1 == other.myFirst1) &&
(this->myLast1 == other.myLast1) &&
(this->myFirst2 == other.myFirst2);
}
bool operator!=(const self &other)
{
return !(*this == other);
}
value_type operator*()
{
assert(!IsDone());
return result;
}
self &operator++()
{
assert(!IsDone());
++myFirst1;
++myFirst2;
if(!IsDone())
{
result = myFunction(*myFirst1, *myFirst2);
}
return *this;
}
self operator++(int)
{
assert(!IsDone());
self temp = *this;
++myFirst1;
++myFirst2;
if(!IsDone())
{
result = myFunction(*myFirst1, *myFirst2);
}
return temp;
}
private:
bool IsDone() const
{
return myFirst1 == myLast1;
}
};
// TEST
typedef BinaryTransformIterator<float *, float *, std::multiplies<float> >
iterator;
int main(void)
{
float buffer1[] = { 1, 2, 3, 4, 5 };
float buffer2[] = { 2, 2, 2, 2, 2 };
iterator first(&buffer1[0], &buffer1[5], buffer2);
iterator last;
for(int i = 0; first != last; i++)
{
assert(*first == buffer1 * buffer2);
++first;
}
return 0;
}