2

No. This question in NOT duplicate of When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?

The question asked here is no ways similar to the link described as duplicate.

First question : I am using const_cast below for two cases. one of it works. the other doesn't.

1. int* const //Works.

In this syntax the address to which the variable would point to cannot be changed. So i used const_cast as below and it works:

`
int j=3;
int *k=&j;
int *m=&j;
int* const i=k; 
const_cast<int*>(i)=m; //OK: since i=m would not work so cast is necessary`

2. const int* //Doesn't work.

The address being pointed to can be changed however the value cannot be changed(though can be changed by making the variable point to different address). The const_cast i am using doesn't seem to work here:

`
int j=9;
int *k=&j;
const int* i1=0;
i1=k; //OK
//*i1=10;//ERROR.`

So i tried to typecast as below through various ways but nothing works:

const_cast<int*>(i1)=10;
const_cast<int*>(*i1)=l;
*i1=const_cast<int>(l);
*i1=const_cast<int*>(10);

Second question: Are all the casts available only for pointers and references? Is the following example not valid where no pointer or reference is in picture?

const int a=9;
int b=4;
const_cast<int>(a)=b; //cannot convert from 'int' to 'int'. why is compiler
                      //trying to convert from int to int anyways or fails         
                      //when both the types are same.
Community
  • 1
  • 1
anurag86
  • 1,635
  • 1
  • 16
  • 31
  • 3
    You missed one variation: `*const_cast(i1) = 10;` – molbdnilo Aug 18 '15 at 10:56
  • 1
    You probably want `const_cast(*i1)=10;` for `2` – Piotr Skotnicki Aug 18 '15 at 10:56
  • 1
    and `const_cast(i)=m;` is wrong as well, you probably meant `const_cast(i)=m;` – Piotr Skotnicki Aug 18 '15 at 11:02
  • @Piotr : thanks it works. But could you please explain why it works. the type to which we are casting should match with the RHS. How does int& match with the value 10? – anurag86 Aug 18 '15 at 11:08
  • @piotr: No, i meant const_cast(i)=m; and not const_cast.(i)=m. where int *m=&j; – anurag86 Aug 18 '15 at 11:11
  • @anurag86 `const_cast(i)=m;` won't compile, expression `const_cast` has a prvalue value-category, so it can't be assigned to – Piotr Skotnicki Aug 18 '15 at 11:14
  • @piotr: trust me it works on vs2008. I have cross checked it just now and also tried printing *i before and after the cast. works too. – anurag86 Aug 18 '15 at 11:22
  • @anurag86, don't print just `*i`. Print `i` also. To see whether `i` itself is changing. Also, perhaps initialize `i` with NULL so that you really can see if it is being changed to `m`. – Aaron McDaid Aug 18 '15 at 11:30
  • @Aaron : *i and i change "After" the cast. If i initialize i to NULL and then cast directly to assign to m then the code compiles but crashes during execution. – anurag86 Aug 18 '15 at 11:39
  • @anurag86 *"then the code compiles but crashes during execution."* a crash is a great example of UB – Piotr Skotnicki Aug 18 '15 at 11:57
  • @piotr: Actually it crashes in both the following cases irrespective i use const_cast(i)=m; or const_cast(i)=m; . though i couldnt still understand the meaning of (i)=m – anurag86 Aug 18 '15 at 12:04
  • @anurag86 `&` denotes you want a modifiable reference to the original expression, otherwise `static_cast` would create a new temporary object that can't be assigned to – Piotr Skotnicki Aug 19 '15 at 07:18

2 Answers2

3

const_cast is applied to expressions, not objects, and itself is an expression as well:

§ 5.2.11 [expr.const.cast]/p1:

The result of the expression const_cast<T>(v) is of type T. If T is an lvalue reference to object type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the expression v

  1. const_cast<int*>(i)=m;

This call is invalid, because the left side of the assignment has a prvalue value-category, and an int* prvalue doesn't support an assignment. The correct syntax would be const_cast<int*&>(i)=m;, but since i in your example was declared const, it would invoke undefined behavior .

  1. const_cast<int*>(*i1)=l;

Dereferencing a pointer of type int* creates an expression of an lvalue value-category, and because the cast expression is on the left side of the assignment, it should be a cast to an lvalue reference type, namely const_cast<int&>(*i1)=10; (provided that whatever i1 points to was not declared const).

  1. const_cast<int>(a)=b;

The const_cast<int>(a) part itself is valid, in particular you can apply a const_cast to an expression representing an object which is not of a pointer type neither of a reference type. But since it's on the left side of the assigment it won't compile. And even if you change it to const_cast<int&>(a)=b; it will trigger undefined behavior, because a is declared const .


§ 7.1.6.1 [dcl.type.cv]/p4:

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
2

First answer: In your example you are trying to force compiler to do something which can be interpreted like this

const_cast<int*>(i1)=10; //int* = int: assign address to pointer
const_cast<int*>(*i1)=l; //const_cast<int*>(int): cast the value under pointer to pointer
*i1=const_cast<int>(l); //const_casting from const values is forbidden
*i1=const_cast<int*>(10); //10 is an rvalue

What you really want to do here is to dereference a pointer that is non-const anymore. That's why you need to do it like this:

int j = 9;
int *k = &j;
const int* i1 = 0;
i1 = k;
*(const_cast<int*>(i1)) = 10;

which is equivalent to

int j = 9;
int *k = &j;
const int* i1 = 0;
i1 = k;
int* temp = const_cast<int*>(i1); //you get rid of 'const'...
*temp = 10; //...and now you assign value as you wanted to - this operation became available

Second answer: It is forbidden to const_cast const values as it leads to undefined behavior. You are only allowed to remove constness from pointers or references that points to something that is not really const in the end and only the pointer disallows you to modify its value.

This issue is awesomely described in this answer.

Community
  • 1
  • 1
psliwa
  • 1,094
  • 5
  • 9