casting away the constness using const_cast

6.2k Views Asked by At

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.
2

There are 2 best solutions below

0
On BEST ANSWER

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.

1
On

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.