Reputation: 158
My understanding is that the const in an argument declaration represents that the function being declared will not change the const value. So why does this ever place a demand on the constness of the argument passed by the caller?
The defining code:
void Func(const Foo**);
main()
{
Foo* fooPtr;
Func(&fooPtr);
}
Visual Studio 2012 compiler yields:
> error C2664: 'Func' : cannot convert parameter 1 from 'Foo**' to 'const Foo**'
> Conversion loses qualifiers
But the following works:
main()
{
Foo* fooPtr;
Func(const_cast<const Foo**>(&fooPtr));
}
What is the underlying theory?
Upvotes: 2
Views: 118
Reputation: 158
When it is the case that Func(&fooPtr) indeed modifies fooPtr while leaving *fooPtr unchanged, there should be two versions of Func(), one defined in terms of the other:
void Func(const Foo**);
void Func(Foo** fooHndl)
{
Func(const_cast<const Foo**>(fooHndl));
}
This allows Func() to be called with a handle (**) to either a const or non-const object.
Upvotes: 0
Reputation: 254431
If the conversion were allowed, then it could be used to circumvent const-correctness:
const Foo const_foo;
void evil(const Foo** p) {
*p = &const_foo; // *p is 'const Foo*', so this assignment is allowed
}
int main() {
Foo* p;
evil(&p); // modifies p to point to const_foo
p->modify(); // BOOM! Modifying a constant object
}
You can convert to const Foo* const*
; that doesn't allow you to change the Foo*
to point to anything else, so can't break const-correctness. That would be better than using a dodgy cast and hoping for the best; although you should ask yourself why you're not simply passing the pointer by value, if you don't want to change it.
Upvotes: 4