8

I was wondering whether the following is undefined behavior

// Case 1:
int *p = 0;
int const *q = *const_cast<int const* const*>(&p);

// Case 2: (I think this is the same)
int *p = 0;
int const *const *pp = &p;
int const *q = *pp;

Is this undefined behavior by reading a int* as if it were a int const*? I think it is undefined behavior, but I previously thought that only adding const in general is safe, so I'm unsure.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • You are asking us! :-) As a matter of interest, do you have a real world use case for this? And like you, I've always assumed that adding constness can't break anything. –  May 11 '11 at 20:06
  • @unapersson ah I just read the last c++0x spec and it turns out it has the answer! I was discussing this problem with my colleague today, who added "const" to a "T" for "T*" as an interator adapter and ran into a problem that begged for this implicit conversion. – Johannes Schaub - litb May 11 '11 at 20:08
  • I think this is totally fine and I don't see anything dangerous here. – Kiril Kirov May 11 '11 at 20:10
  • Do you mean to imply that passing e.g. a `double*` to a function taking a `double const*` would cause UB? I'd be amazed if this were true – ildjarn May 11 '11 at 20:27
  • @ildjarn: a related issue is whether passing a converted `double **` into a function taking a `double const**` is UB (when that function uses it), but the example you give is not a consequence of this being UB. If this even is UB, I mean. – Steve Jessop May 11 '11 at 20:55

1 Answers1

5

Qualification-wise, it's fine. With each expression split into a statement:

int *p = 0; // ok
int **addrp = &p; // ok
int const *const *caddrq = addrp; // ok, qualification conv. according to §4.4/4
int const *q = *caddrq; // ok

Note that the rules of const_cast (§5.2.11/3) are identical to those of qualification conversion, but without the requirement of being monotonically increasing in qualification. In your case, because you're only ever adding qualifications the const_cast is unnecessary.


Concerning aliasing, I don't think it's an issue, here, or at least it's not intended to be.

Like you mentioned, there's a new bullet in the C++0x list of allowed access methods (§3.10) that allows similar types ("similar" being types arising from qualification conversions). In C++03 that bullet is missing, but I suspect that the bullet about allowing more cv-qualified access was meant to cover that, but it technically isn't so (that is, the commitee overlooked this).

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • @GMan i mean, if I read the "int*" by an lvalue of type "int const*" is this not an aliasing violation? When I looked into the spec today, I seem to have missed that they added a new bullet for C++0x to the aliasing rule list! – Johannes Schaub - litb May 11 '11 at 20:14
  • @GMan "int const*" is not a more cv-qualified version of "int*". "int * const" would be. – Johannes Schaub - litb May 11 '11 at 20:23
  • @Johannes: Oh, yes, I get it now and I see that too. That's interesting, because I think the intent of the bullet I now mention in my answer was to cover the newly added bullet, but there must have been an overlook (or I'm just expecting to much from it). Do you know why that is? – GManNickG May 11 '11 at 20:23
  • 1
    Thanks for the answer! For the formalities: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#158 – Johannes Schaub - litb May 11 '11 at 21:13