Bob Brandt
Bob Brandt

Reputation: 158

Why must an argument ever be cast to const?

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

Answers (2)

Bob Brandt
Bob Brandt

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

Mike Seymour
Mike Seymour

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

Related Questions