Adapters library: using back_insertor with make_transform_iterator
How does this work?
I'm trying to use the make_transform_iterator to make a writeable output
iterator (looks like it is referred to as a "Writeable LValue" in the
iterator template code), but I can't figure out how to do it.
Here's the example: (I know that I could have used the
make_transform_iterators on the source iterators in this toy example, but
that won't do for my real application)
typedef map
::type,
CategoryOrTraversal=boost::mpl::identityboost::incrementable_traversal_tag
::type,
Reference=boost::mpl::identity
::type,
Difference=boost::iterator_difference
"Robert Mathews"
How does this work?
I'm trying to use the make_transform_iterator to make a writeable output iterator (looks like it is referred to as a "Writeable LValue" in the iterator template code
Don't look at the code; read the documentation. The meaning of "writeable lvalue iterator" is detailed in the paper here: http://www.boost.org/libs/iterator/doc/index.html#new-style-iterators
), but I can't figure out how to do it.
Here's the example: (I know that I could have used the make_transform_iterators on the source iterators in this toy example, but that won't do for my real application)
typedef map
Map; typedef vector<int> V1; typedef vector<string> V2; string convert(int iValue) { return str(ostringstream() << iValue); } int _tmain(int argc, _TCHAR* argv[]) { V1 aSourceVector; V2 aTargetVector; copy(aSourceVector.begin(), aSourceVector.end(), make_transform_iterator(back_inserter(aTargetVector), boost::bind(convert, _1)); }
Okay, let's review what a transform_iterator does, from http://www.boost.org/libs/iterator/doc/transform_iterator.html: The transform iterator adapts an iterator by modifying the operator* to apply a function object to the result of dereferencing the iterator and returning the result. So your transform_iterator's operator* is going to apply convert to the result of dereferencing a back_insert_iterator. Okay, that's your first problem. Do you know what you get when you dereference a back_insert_iterator? According to my copy of the standard, back_insert_iterator's operator* has the following signature: back_insert_iterator<Container>& operator*(); In other words, it returns a reference to a back_insert_iterator. Since convert takes an int, you have an impedance mismatch. Sounds like you want something more like function_output_iterator: http://www.boost.org/libs/iterator/doc/function_output_iterator.html It doesn't adapt an iterator, and I'm guessing you don't really want to adapt an iterator anyway (you could just use push_back, or more likely in your case, operator<<), but if I'm wrong, you can always embed the iterator in the function object you adapt. HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com
Yes, that's what I needed, thank you very much. FWIW, I couldn't find
make_function_output_iterator when I first looked at the documentation, and
then I ended out trying to read the code in the iterators library instead
... which was about when I gave up and posted.
I rewrote it as follows, binding to the convert function and then sending
that result to the push_back, and it now looks like the following.
Unfortunately, vector::push_back is overloaded, so that the cast is really
ugly. But it works.
int _tmain(int argc, _TCHAR* argv[])
{
V1 aSourceVector;
V2 aTargetVector;
aSourceVector.push_back(43);
copy(aSourceVector.begin(),
aSourceVector.end(),
make_function_output_iterator(
boost::bind((void (vector<string>::*)(const
string&))&vector<string>::push_back,
boost::ref(aTargetVector),
boost::bind(convert,_1))));
}
"David Abrahams"
"Robert Mathews"
writes: How does this work?
I'm trying to use the make_transform_iterator to make a writeable output iterator (looks like it is referred to as a "Writeable LValue" in the iterator template code
Don't look at the code; read the documentation. The meaning of "writeable lvalue iterator" is detailed in the paper here: http://www.boost.org/libs/iterator/doc/index.html#new-style-iterators
), but I can't figure out how to do it.
Here's the example: (I know that I could have used the make_transform_iterators on the source iterators in this toy example, but that won't do for my real application)
typedef map
Map; typedef vector<int> V1; typedef vector<string> V2; string convert(int iValue) { return str(ostringstream() << iValue); } int _tmain(int argc, _TCHAR* argv[]) { V1 aSourceVector; V2 aTargetVector; copy(aSourceVector.begin(), aSourceVector.end(), make_transform_iterator(back_inserter(aTargetVector), boost::bind(convert, _1)); }
Okay, let's review what a transform_iterator does, from http://www.boost.org/libs/iterator/doc/transform_iterator.html:
The transform iterator adapts an iterator by modifying the operator* to apply a function object to the result of dereferencing the iterator and returning the result.
So your transform_iterator's operator* is going to apply convert to the result of dereferencing a back_insert_iterator. Okay, that's your first problem. Do you know what you get when you dereference a back_insert_iterator?
According to my copy of the standard, back_insert_iterator's operator* has the following signature:
back_insert_iterator<Container>& operator*();
In other words, it returns a reference to a back_insert_iterator. Since convert takes an int, you have an impedance mismatch.
Sounds like you want something more like function_output_iterator: http://www.boost.org/libs/iterator/doc/function_output_iterator.html
It doesn't adapt an iterator, and I'm guessing you don't really want to adapt an iterator anyway (you could just use push_back, or more likely in your case, operator<<), but if I'm wrong, you can always embed the iterator in the function object you adapt.
HTH,
-- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (2)
-
David Abrahams
-
Robert Mathews