Consider this
void f(vector& p)
{
}
int main()
{
vector nonConstVec;
f(nonConstVec);
}
The followi
It may be worth showing why it's a breach of const-correctness to perform the conversion you want:
#include
const int a = 1;
void addConst(std::vector &v) {
v.push_back(&a); // this is OK, adding a const int* to a vector of same
}
int main() {
std::vector w;
int b = 2;
w.push_back(&b); // this is OK, adding an int* to a vector of same
*(w.back()) = 3; // this is OK, assigning through an int*
addConst(w); // you want this to be OK, but it isn't...
*(w.back()) = 3; // ...because it would make this const-unsafe.
}
The problem is that vector takes a pointer-to-non-const (which I'll call a "non-const pointer" from now on). That means, it might modify the pointee of its parameter. Specifically in the case of vector, it might hand the pointer back out to someone else who modifies it. So you can't pass a const pointer to the push_back function of w, and the conversion you want is unsafe even if the template system supported it (which it doesn't). The purpose of const-safety is to stop you passing a const pointer to a function which takes a non-const pointer, and this is how it does its job. C++ requires you to specifically say if you want to do something unsafe, so the conversion certainly can't be implicit. In fact, because of how templates work, it's not possible at all (see later).
I think C++ could in principle preserve const-safety by allowing a conversion from vector to const vector, just as int ** to const int *const * is safe. But that's because of the way vector is defined: it wouldn't necessarily be const-safe for other templates.
Likewise, it could in theory allow an explicit conversion. And in fact, it does allow an explicit conversion, but only for objects, not references ;-)
std::vector x(w.begin(), w.end()); // conversion
The reason it can't do it for references is because the template system can't support it. Another example that would be broken if the conversion were allowed:
template
struct Foo {
void Bar(T &);
};
template<>
struct Foo {
void Baz(int *);
};
Now, Foo doesn't have a Baz function. How on earth could a pointer or reference to Foo be converted to a pointer or reference to Foo?
Foo f;
Foo &g = f; // Not allowed, but suppose it was
int a;
g.Baz(&a); // Um. What happens? Calls Baz on the object f?