Neil Kirk
Neil Kirk

Reputation: 21773

Conversion from Derived** to Base*const*

Please read my question before linking parashift, I can google search, this is slightly different case.

This isn't allowed

Child **cc;
Base ** bb = cc;

Because you could do

*bb = new OtherChild;

But if we have

Child **cc;
const Base *const *const bb = cc;

I don't think all those const are necessary for my example, but just to be sure..

I think the minimum which should work is

Base *const *bb = cc;

Then you can't do this

*bb = new OtherChild;

So it should be safe. But why isn't it allowed?

Upvotes: 9

Views: 614

Answers (3)

Ben Voigt
Ben Voigt

Reputation: 283634

You're confusing two cases:

  • The addition of const
  • Upcasts

While formally (in computer science theory) both of these deal with subclassing, the reality is that the C++ rules for these are different, because the representation of const T and T are guaranteed to be the same, while the representations of Base* and Derived* often differ by an offset (but may be radically different when virtual inheritance is involved).

In 3.9.3, the Standard declares that

The cv-qualified or cv-unqualified versions of a type are distinct types; however, they shall have the same representation and alignment requirements

Given:

struct Base {};
struct Derived : Base {};
Derived* pd = nullptr;
Base* pb = pd;

const can indeed by added in the way you suggest.

Base const* const* const cpcpcb = &pb;
Base* const* pcpb = &pb; // legal, pointer can't be changed
Base const* * ppcb = &pb; // illegal, one could try to rebind the pointer
                          // to a truly const object, then
                          // use pb to mutate the const object

But there is no is-a relationship between Derived* and Base*. A conversion exists, but the Derived* variable does not necessarily contain the address of a Base object (the Base subobject within the Derived object may have a different address). And therefore both the line you're complaining about, and the line your question assumed was valid, are illegal:

Base const* const* const cpcpcd = &pd; // error, there's no address of a Base
                                       // to be found in pd
Base* const* pcpd = &pd; // error: again, there's no address of a Base
                         // stored in pd

Formally, the Standard describes this in 4.10:

A prvalue of type "pointer to cv D”, where D is a class type, can be converted to a prvalue of type "pointer to cv B", where B is a base class of D. If B is an inaccessible or ambiguous base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion is a pointer to the base class subobject of the derived class object. The null pointer value is converted to the null pointer value of the destination type.

The result of the conversion is a prvalue, it doesn't have an address, and you can't create a pointer to it.

Upvotes: 6

jxh
jxh

Reputation: 70392

This is a constraint imposed by the C++ language, because implicit conversion of pointer types is based on inheritance rules (with the exception of implicit conversion to void *).

That is, given the following program, the assignment is only allowed if T is a base of U:

T const *x;
U *y;
x = y;

However, in your case:

typedef Base *T;
typedef Child *U;

The relationship between Base and Child does not transfer to their pointer types. So, there is no inheritance relationship between "pointer to Base" and "pointer to Child" to allow the direct assignment you desire.

Upvotes: 1

user2485710
user2485710

Reputation: 9801

I think that in your equation you are expecting const to play a bigger role than what it really has.

const is a qualifier, and simply put, its role is to regulate the way you access a type or a variable.

The main point is if the language itself, without even considering what is const or not, already regulates a given behaviour, your specific case is not that different from the one reported by that FAQ.

You are in a really simple situation, and you should probably think in much simpler terms.

Upvotes: 0

Related Questions