Monday, March 31, 2008

const_cast casting operator

Today I want to explain about the const_cast C++ operator.

const_cast is a new operator introduced in C++, for casting purposes. The const_cast can is used to explicitly override const and/or volatile in a cast.

The usage format of this operator is as follows,

const_cast<target_type>(expression)
The target type must be the same as the source type of the expression except const and/or volatile attributes.

This casting operator can be used, either to introduce or remove const-ness or valatile-ness from a expression.

To explain the need of const_cast I will take following example.

Consider following program.
/*
* Copyright (c) 2009 Raghavendra Nayak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/*
* Note: This program shows how to get square of a number using object reference.
*/


#include <iostream>
#include <cstdlib>

void
square(int &number)
{

number *= number;
}


int
main(void)
{

int
number;

std::cout<<"\nEnter a input number: ";
std::cin>>number;

std::cout<<"\nThe input number is "<<number<<std::endl;

// call square function
square(number);

std::cout<<"\nThe square of input is "<<number<<std::endl;

return
EXIT_SUCCESS;
}

In this program, function square takes a reference and returns the square of the number through number itself.

compile this program by typing following command

$ g++ const_cast_1.cpp -o const_cast_1
run this program as

$ ./const_cast_1
run data

Enter a input number: 4
The input number is 4
The square of input is 16

now lets modify this program's square function to take a constant reference instead of normal reference.

code is given below.
/*
* Copyright (c) 2009 Raghavendra Nayak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

/*
* Note: This file will not compile properly as we are trying to modify
* a constant reference inside the function, which is not allowed.
*/


#include <iostream>
#include <cstdlib>

void
square(const int &number)
{

number *= number;
}


int
main(void)
{

int
number;

std::cout<<"\nEnter a input number: ";

std::cin>>number;

std::cout<<"\nThe input number is "<<number<<std::endl;

// call square function
square(number);

std::cout<<"\nThe square of input is "<<number<<std::endl;

return
EXIT_SUCCESS;
}

Now try to compile this program.

$ g++ const_cast_2.cpp -o const_cast_2
You will end up in compilation error. The error is

const_cast_2.cpp: In function ‘void square(const int&)’:
const_cast_2.cpp:33: error: assignment of read-only reference ‘number’

Hmm, how to fix this problem ?

Check the following code, where we use const_cast and nullify the constness of input number.
/*
* Copyright (c) 2009 Raghavendra Nayak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/


#include <iostream>
#include <cstdlib>

void
square(const int &number)
{

int
*pointer_to_number = NULL;

// remove the constness
pointer_to_number = const_cast<int *>(&number);

*
pointer_to_number *= number;

// above line can be replaced with any one of the following lines

//*pointer_to_number = number * number;
//*pointer_to_number = *pointer_to_number * *pointer_to_number;
//*pointer_to_number = (*pointer_to_number) * (*pointer_to_number);
}

int
main(void)
{

int
number;

std::cout<<"\nEnter a input number: ";
std::cin>>number;

std::cout<<"\nThe input number is "<<number<<std::endl;

// call square function
square(number);

std::cout<<"\nThe square of input is "<<number<<std::endl;

return
EXIT_SUCCESS;
}
compile this program by typing

$ g++ const_cast_3.cpp -o const_cast_3
run this program by typing

$ ./const_cast_3
run data

Enter a input number: 4
The input number is 4
The square of input is 16

Voila, no compilation errors and output is also perfect!

This is the magic of const_cast.

* PENDING *

advantages: PENDING.
Disadvantages: PENDING.
Use Cases: PENDING.
Downloads: PENDING.

2 comments:

Anonymous said...

Hi Raghu,

Please provide some examples...
That will help us understand better.

-Damu

Raghu Nayak said...

Hi,

I have included a sample as per your request. Check it out..