C++ difference between adding const-ness with static_cast and const_cast of “this” object?

StackOverflow https://stackoverflow.com/questions/11127572

  •  16-06-2021
  •  | 
  •  

Question

As per Scott Meyers, to prevent repetition of code in the const version of a getter and the non-const version of a getter, call the const version of the method from the non-const version: static_cast<const A&>(*this).Methodology(); however, in accidental usage due to an overzealous Visual Assist X Intellisense I typed: const_cast<const A&>(*this).Methodology(); and it worked just fine.

What are any and all differences in this case with using a particular cast?

IDE in use: Visual Studio 2010.

Was it helpful?

Solution

Assuming that the type of this is A*, there is no difference.

In general const_cast can cast aways the const specifier (from any level of indirection or template parameter)

static_cast<> can cast a type to another if the target type is in the source's type hierarchy.

They cannot do each other's work.

The reason they both worked in your case is because you have introduced const-ness, as opposed to having taken it away (calling from the non-const version of the function the type of this is A*, no const). You could just as well have written

const A& tmp = *this;
tmp.Methodology();

and it would have worked without the need for any casting. The casting is used for convenience and terseness to not have to introduce a new variable.

Note: you can use static_cast<> here as you know that you are casting to the right type. In other cases (when you cannot be sure) you need to use dynamic_cast<> that does a runtime type check to ensure the conversion is valid

OTHER TIPS

After re-reading Item 3 from Effective C++ 3rd Ed. I realize that he was actually advocating using both. Add const to call the const version, then cast away the const-ness of the return value (if there is one). In my particular case, there is no const return value, just a const-function so the wrapped-by-const_cast<> version is not needed and in effect causes there to be no difference between the two calls in question

(p. 13) Item 3: Use const whenever possible

...

(p. 23) Avoiding Duplication in const and Non- const Member Functions

...What you really want to do is implement operator[] functionality once and use it twice. That is, you want to have one version of operator[] call the other one. And that brings us to casting away constness.

...Casting away the const on the return value is safe, in this case, because whoever called the non-const operator[] must have had a non-const object in the first place....So having the non-const operator[] call the const version is a safe way to avoid code duplication, even though it requires a cast...

class TextBlock {
public:

...

    const char& operator[](std::size_t position) const      //same as before
    {
        ...
        ...
        ...
        return text[position];
    }

    char& operator[](std::size_t position)        //now just calls const op[]
    {
        //cast away const on op[]'s return type;
        //add const to *this's type;
        //call const version of op[].
        return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
    }
...
};

As you can see, the code has two casts, not one. We want the non-const operator[] ... To avoid infinite recursion, we have to specify that we want to call the const operator[], but there's no direct way to do that. Instead, we cast *this from its native type of TextBlock& to const TextBlock&. Yes, we use cast to add const! So we have two casts: one to add const to *this (so that our call to operator[] will call the const version), the second to remove the const from the *const operator[]'s return value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top