Avoiding duplication of code in const and non-const getter methods

suggest change

In C++ methods that differs only by const qualifier can be overloaded. Sometimes there may be a need of two versions of getter that return a reference to some member.

Let Foo be a class, that has two methods that perform identical operations and returns a reference to an object of type Bar:

class Foo
{
public:
    Bar& GetBar(/* some arguments */)
    {
        /* some calculations */
        return bar;
    }
    
    const Bar& GetBar(/* some arguments */) const
    {
        /* some calculations */
        return bar;
    }

    // ...
};

The only difference between them is that one method is non-const and return a non-const reference (that can be use to modify object) and the second is const and returns const reference.

To avoid the code duplication, there is a temptation to call one method from another. However, we can not call non-const method from the const one. But we can call const method from non-const one. That will require as to use ‘const_cast’ to remove the const qualifier.

The solution is:

struct Foo
{
    Bar& GetBar(/*arguments*/)
    {
        return const_cast<Bar&>(const_cast<const Foo*>(this)->GetBar(/*arguments*/));
    }
    
    const Bar& GetBar(/*arguments*/) const
    {
        /* some calculations */
        return foo;
    }
};

In code above, we call const version of GetBar from the non-const GetBar by casting this to const type: const_cast<const Foo*>(this). Since we call const method from non-const, the object itself is non-const, and casting away the const is allowed.

Examine the following more complete example:

#include <iostream>

class Student
{
public:
    char& GetScore(bool midterm)
    {
        return const_cast<char&>(const_cast<const Student*>(this)->GetScore(midterm));
    }
    
    const char& GetScore(bool midterm) const
    {
        if (midterm)
        {
            return midtermScore;
        }
        else
        {
            return finalScore;
        }
    }
    
private:
    char midtermScore;
    char finalScore;
};

int main()
{
    // non-const object
    Student a; 
    // We can assign to the reference. Non-const version of GetScore is called
    a.GetScore(true) = 'B';
    a.GetScore(false) = 'A';
    
    // const object
    const Student b(a); 
    // We still can call GetScore method of const object,
    // because we have overloaded const version of GetScore
    std::cout << b.GetScore(true) << b.GetScore(false) << '\n'; 
}

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


const keyword:
* Syntax
* Avoiding duplication of code in const and non-const getter methods

Table Of Contents
8 Arrays
10 const keyword
11 Loops
39 Streams
51 Unions
56 Lambdas
60 SFINAE
62 RAII
67 Sorting
84 RTTI
87 Scopes
104 Profiling
107 Recursion
117 Iteration
125 Alignment
134 Semaphore
136 Debugging
139 Mutexes
142 decltype