Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it okay to remove const qualifier when the call is from the same non-const version overloaded member function?

For example:

struct B{};

struct A {

 const B& findB() const { /* some non trivial code */ }

 // B& findB() { /* the same non trivial code */ }

 B& findB() { 
       const A& a = *this;
       const B& b = a.findB();
       return const_cast<B&>(b);
  }
};

The thing is I want to avoid repeating the same logic inside the constant findB and non-constant findB member function.

like image 947
dchhetri Avatar asked Dec 06 '12 19:12

dchhetri


People also ask

What will happen if a const object calls a non-const member function?

If the function is non-constant, then the function is allowed to change values of the object on which it is being called. So the compiler doesn't allow to create this chance and prevent you to call a non-constant function on a constant object, as constant object means you cannot change anything of it anymore.

How do I remove const qualifier?

The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a . This process of using const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler does allow the function call f(c) .

What is the use of having the const qualifier?

The const qualifier explicitly declares a data object as something that cannot be changed. Its value is set at initialization. You cannot use const data objects in expressions requiring a modifiable lvalue. For example, a const data object cannot appear on the lefthand side of an assignment statement.

How is it possible to have both const and non-const version of a function?

There are legitimate uses of having two member functions with the same name with one const and the other not, such as the begin and end iterator functions, which return non-const iterators on non-const objects, and const iterators on const objects, but if it's casting from const to do something, it smells like fish.


1 Answers

Yes, you can cast the object to const, call the const version, then cast the result to non-const:

return const_cast<B&>(static_cast<const A*>(this)->findB());

Casting away const is safe only when the object in question was not originally declared const. Since you are in a non-const member function, you can know this to be the case, but it depends on the implementation. Consider:

class A {
public:

    A(int value) : value(value) {}

    // Safe: const int -> const int&
    const int& get() const {
        return value;
    }

    // Clearly unsafe: const int -> int&
    int& get() {
        return const_cast<int&>(static_cast<const A*>(this)->get());
    }

private:
    const int value;
};

Generally speaking, my member functions are short, so the repetition is tolerable. You can sometimes factor the implementation into a private template member function and call that from both versions.

like image 181
Jon Purdy Avatar answered Nov 08 '22 13:11

Jon Purdy