0

https://stackoverflow.com/a/332086/462608

modifying a formerly const value is only undefined if the original variable is const

...

if you use it to take the const off a reference to something that wasn't declared with const, it is safe.

...

This can be useful when overloading member functions based on const, for instance. It can also be used to add const to an object, such as to call a member function overload.

I am unable to understand the meanings of the above quotes. I request you to give me examples to practically show what these quotes mean.

Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411
  • [The example code](https://en.cppreference.com/w/cpp/language/const_cast#Example) on cppreference.com provides some useful exposition. – G.M. Aug 28 '20 at 08:32
  • Regarding the first point, it's important to understand WHY const_casting a const variable is undefined. [This answer](https://stackoverflow.com/a/56141131/3672674) explains it nicely – NotAProgrammer Aug 28 '20 at 08:44
  • "formerly" is a typo, it probably is meant to be "formally" – Caleth Aug 28 '20 at 12:14

2 Answers2

6

Regarding your first two quotes:

void do_not_do_this(const int& cref) {
    const_cast<int&>(cref) = 42;
}

int main() {
    int a = 0;
    // "if you use it to take the const off a reference 
    // to something that wasn't declared with const, it is safe."
    do_not_do_this(a);  // well-defined
        // a is now 42.
    
    // "modifying a formerly const value is only 
    //  undefined if the original variable is const"
    const int b = 0;
    do_not_do_this(a);  // undefined behavoiur
}

Regarding your final quote:

// "This can be useful when overloading member functions based
//  on const, for instance. It can also be used to add const
//  to an object, such as to call a member function overload."
class A {
    const int& get() const
    {
        // ... some common logic for const and
        // non-const overloads.
        return a_;
    }

    int& get() {
        // Since this get() overload is non-const, the object itself
        // is non-const in this scope. Moreover, the a_ member
        // is non-const, and thus casting away the const of the return
        // from the const get() (after 'this' has been casted to
        // const) is safe.
        A const * const c_this = this;
        return const_cast<int&>(c_this->get());
    }
    
private:
    int a_{0}; 
}
G. Sliepen
  • 7,637
  • 1
  • 15
  • 31
dfrib
  • 70,367
  • 12
  • 127
  • 192
3

How about this:

#include <iostream>
void foo(const int& ub, const int& ok)
{
    const_cast<int&>(ub) = 0.0; // undefined behaviour - the original object is const
    const_cast<int&>(ok) = 1.0; // this is fine - the original object is not const
}

int main()
{
    const int ub = 1.0;
    int ok = 0.0;
    foo(ub, ok);
    std::cout << ub << " " << ok << std::ends;
}

Note the output on common compilers is 1 1: the rationale being that the compiler knows that ub cannot change in main so it substitutes 1 for ub in the std::cout call.

Your third paragraph is alluding to a function body of a non-const member function calling the const version as a means of obviating code repetition.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483