4

Consider the following piece of code:

#include <iostream>

using namespace std;

class A {
    private:
    int x;
    public:
    int& get_ref() {
        cerr << "non const" << endl;
        return x;
    }

    const int& get_ref() const {
        cerr << "const" << endl;
        return x;
    }
};

int main () {
    A a;
    a.get_ref() = 10;

    cout << a.get_ref() << endl;

    const int& y = a.get_ref();

    return 0;
}

I expect the second and third calls to a.get_ref() to run the second version of get_ref() method (and output const on the standard error). But it looks like always the first version is called. How can I implement two different 'getter's and make sure that the proper version is called based on the context? I.e., at least for the third call

const int& y = a.get_ref();

the second version is executed? (A non-elegant solution would be to use different names e.g. get_ref and get_const_ref but I am trying to see if that can be avoided.)

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
MikeL
  • 2,369
  • 2
  • 24
  • 38

2 Answers2

7

Overload resolution doesn't depend on return values, but only arguments, including the object to be called on for member function. a is a non-const object, then for a.get_ref(), the non-const member function will always be called.

You can cast it to const for the const version to be called:

const_cast<const A&>(a).get_ref();

BTW: Giving them different names is not a bad idea. That's why we have std::cbegin and std::cend in STL.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Thanks for the clarification! So, this, in particular, means that any call to `get_ref` from inside the class will be resolved to the first (non-const) version (unless we cast `this` to `const` similarly to what you suggested). Am I right? – MikeL May 02 '17 at 09:37
  • 2
    @PBM More precisely, any call to `get_ref` from the member functions of the class, the resolution depends on `this` points to `const` or `non-const`, i.e. the member function being called firstly is `const` or not. So inside a `const` member function, when calling `get_ref`, the const `get_ref` will be called; inside a non-const member function, non-const `get_ref` will be called. – songyuanyao May 02 '17 at 09:40
0

Overload resolution is concerned only with the arguments of the call (including the implicit argument for this). The expression a.get_ref() must evaluate to the same overload regardless of what happens with its returned value. That is fundamental in C++, and there's nothing you can do about it.

If you want to call the const-qualified version, use a const-qualified object expression:

const int& y = const_cast<const A&>(a).get_ref();
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • There are of course workaround possible, based on the concrete situation you want to handle. If you specify *why* you want such behaviour, I might come up with a workaround for it. It will be ugly and discouraged, but might be possible. – Angew is no longer proud of SO May 02 '17 at 09:35