Reputation: 1784
I am trying to understand STL algorithms.
Copy is defined as :
template<class InputIterator, class OutputIterator>
OutputIterator copy ( InputIterator first, InputIterator last, OutputIterator result )
Can some one please explain why does the following works when vectors & deques are mixed but fails when vectors and sets are mixed.
#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#include <deque>
#include <set>
using namespace std;
int main () {
int myints[]={10,20,30,40,50,60,70};
vector<int> myvector;
vector<int>::iterator it;
set<int> mset(myints,myints+8);
set<int>::iterator setItr = mset.begin();
deque<int> deq;
deq.resize(10);
deque<int>::iterator deqItr = deq.begin();
myvector.resize(7); // allocate space for 7 elements
copy ( myints, myints+7, myvector.begin() );
copy ( myvector.begin(), myvector.end(), deqItr );
cout << "deque contains:";
for (deque<int>::iterator dit=deq.begin(); dit!=deq.end(); ++dit)
cout << " " << *dit;
cout << endl;
//copy ( myvector.begin(), myvector.end(), setItr );
return 0;
}
I understand vectors/deque have random access iterators, where as set's have bidirectional iterators. I fail to understand why compilation fails when only a input/output iterators are required.
PS : This is just an experiment to increase my understanding :)
Upvotes: 2
Views: 3164
Reputation: 490108
std::vector
and std::deque
have a way to preallocate space. std::set
doesn't. Without preallocating the space, attempting to dereference the iterator you pass to copy
produces undefined behavior.
The obvious alternative is to use insert iterators instead -- though, unfortunately, you still neednearly always use different code for a set than a deque or vector:
std::copy(myvector.begin(), myvector.end(), std::back_inserter(mydeque));
std::copy(myvector.begin(), myvector.end(), std::inserter(mySet, mySet.end());
Upvotes: 5
Reputation: 208343
Associative containers (in plain C++03) are special containers that keep their elements sorted at all times, commonly implemented as a Red Black Tree. To maintain the order invariant, the set and map iterators provide constant references into the key object, and as such you cannot modify it.
In particular for std::set<T>
, the iterator will usually be such that std::iterator_traits< std::set<T>::iterator >::reference
is const T&
, and as such the assignment implicit in the std::copy
operation will fail.
If what you want to do is insert the elements into a set, you can use iterators from the <iterator>
header that will perform insert
operations in the set:
std::copy( v.begin(), v.end(), std::inserter( s, s.end() ) ); // s is the set
Upvotes: 5
Reputation: 92261
It works for vector and deque because you can allocate space beforehand. With other containers, like map, you need an iterator adapter to do that for you. Look at insert_iterator, for example.
Upvotes: 0