Re: iterator_traits::value_type on back_insert_iterator - returns
void
anto.anish@gmail.com wrote:
Hello,
My Requirement is
1. Copy data from iterator to an array ( array should be created
dynamically within the function based on data_type of the data
held by the iterator /container. )
2. Copy data from array into iterator ( array should be created
dynamically within the function based on data_type of the data
held by the iterator /container. )
Implementation
-----------------------
//copies data from begin to end of container to array.
template <class T>
void writeiter( T& iter1, T& iter2)
{
int t2= iter2 -iter1;
cout <<t2<<endl;
iterator_traits<T>::value_type *twrite= new
iterator_traits<T>::value_type[t2];
std::copy(iter1,iter2,twrite);
}
//copies data from array to iter (back_insert_iterator)
template <class T> void readiter( T& iter, int len)
{
//This line does not compile since return is a void.
iterator_traits<T>::value_type *tread= new
iterator_traits<T>::value_type[len]; for (int i=0; i<len;++i)
tread[i] = i;
std::copy(tread, tread+ len,iter );
}
int main()
{
vector <int> v1;
int len=5;
back_insert_iterator< vector<int> > v1back(v1);
readiter(v1back,len); //Does not work - the function does not compile
vector<int>::iterator vbdir1=v1.begin();
vector<int>::iterator vbdir2=v1.end();
writeiter(vbdir1,vbdir2); //works good
}
The readiter function does not compile since a
iterator_trait::value_type of back_insert_iterator's returns void.
what i would need is to get the datatype of the container which is INT
held by the back_insert_iterator. My assumption was that i would get
the iterator_traits of back_insert_iterator from function readiter ,
which would later be used to create an array or a array of pointers.
Any help appreciated?
Thanks
Anish
I personally have never understood why iterator_traits::value_type is
void for output iterators: *i = t must work for some (apparently not
void) type of t so IMHO there is nothing wrong in letting client code
know this type.
Anyway, I slightly changed your code to work for me, like this:
#include <iostream>
#include <vector>
using namespace std;
template <class T>
void writeiter( T& iter1, T& iter2) {
typedef typename iterator_traits<T>::value_type ValType;
int t2= iter2 -iter1;
cout <<t2<<endl;
ValType *twrite= new ValType[t2];
std::copy(iter1,iter2,twrite);
}
template <class T> void readiter( T& iter, int len) {
typedef typename T::container_type::value_type ValType;
ValType *tread= new ValType[len];
for (int i=0; i<len;++i) tread[i] = i;
std::copy(tread, tread+ len,iter );
}
int main() {
vector<int> v1;
int len=5;
back_insert_iterator< vector<int> > v1back(v1);
readiter(v1back,len);
vector<int>::iterator vbdir1=v1.begin();
vector<int>::iterator vbdir2=v1.end();
writeiter(vbdir1,vbdir2); //works good
}
It is certainly not a generic solution so I would rather add a second
type parameter to readIter (I know you try to avoid this) and make some
nasty comment about C++ Standard...
Another way would be to create an adapter, something like
smart_output_iterator, with template parameters for the "raw" output
iterator and for the element type, then create the specialization of
iterator_traits for this adapter. Then, you can specialize that
smart_output_iterator for ??? STL output iterators you need to use with
their peculiar ways of getting the element type (like char_type of
ostream_iterator, container_type::value_type for insert_iterator etc) --
and then use that smart_output_iterator everywhere instead of the
output_iterator. Not sure if your problem warrants all this effort for
you though..
Hope this will help
-Pavel