Reputation: 17441
i ran across something similar to the below code snippet, which throws a compiler error because its using a const_iterator
. is there a reason why vec.end()
in std::copy
does not implicitly get a const
cast ?
int main(int argc, char* argv[]) {
vector<int> vec;
vec.push_back(20);
vec.push_back(30);
vector<int> copy_vec;
vector<int>::const_iterator i = vec.begin();
std::copy(i,vec.end(),back_inserter(copy_vec));
cerr<<copy_vec.size()<<endl;
return 0;
}
Upvotes: 0
Views: 356
Reputation: 361332
No need of std::copy
, neither you need a pair of iterators.
Just do this:
vector<int> copy_vec(vec); //use the copy constructor!
And you're done!
As for your code why it is giving error, is because the first iterator to std::copy
is a const_iterator
, but the second iterator is just iterator
. Both has to be same type, but they are not, and because of that the template argument deduction fails for std::copy
which is a function template.
To understand this with an example, consider this simple code:
template<typename T>
void f(T a, T b) {}
int main()
{
int a = 100;
char b = 'A';
f(a,b);
}
It is giving error (see ideone):
prog.cpp:8: error: no matching function for call to ‘f(int&, char&)’
It doesn't compile because we're relying on template argument deduction. Since the type of the first parameter and second parameter is exactly same in the function template but we call this function passing a
(which is int
) as first argument and b
(which is char
) as second argument, it cannot deduce T
uniquely from arguments of different types! Please note that conversion is not considered during template argument deduction.
However, if we do not rely on template argument deduction, and instead provide the template argument explicitly, then it would work (see ideone):
f<int>(a,b); //works!
It works as there is no need to deduce T
from function arguments!
Similarly, if you provide the template argument for std::copy
, then even your code would work (see ideone):
std::copy<vector<int>::const_iterator>(i,vec.end(),back_inserter(copy_vec));
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^ explicitly provide template argument!
It works because iterator
can convert into const_iterator
, but const_iterator
cannot convert into iterator
which means the following would give error (see ideone):
std::copy<vector<int>::iterator>(i,vec.end(),back_inserter(copy_vec));
//^^^^^^^^^^^^^^^^^^^^^ non-const iterator!
Upvotes: 5
Reputation: 96243
vec
is a non-const vector, and so end
will return a non-const iterator. Such an iterator actually cannot be implicitly converted to a const version, because they're separate classes.
Instead, use the two iterator constructor:
vector<int> copy_vec(vec.begin(), vec.end());
Upvotes: 1
Reputation: 16670
I think that the problem here is that std::copy is declared to take three parameters.
The first two are of the same type, and you are passing ( const_iterator, vec.end () )
- and vec.end() is returning a non-const iterator (because vec is a non-const vector). This causes the compiler to reject the template for std::copy.
If you had a function like this:
void doit ( const std::vector<int> &vec, std::vector<int> &out ) {
std::vector<int>::const_iterator i = vec.begin();
std::copy(i,vec.end(),back_inserter(out));
}
Then it will compile and work fine, because vec.end () will return a const_iterator. Alternately, if you are using C++11, you can call vec.cend () to get a const_iterator.
Upvotes: 0