Assume you have a class T with two member functions
char foo() const {...}
char foo() {...}
.
It is my understanding that when called for a constant T, we resolve to (1); and for a non-constant T, we resolve to (2).
- is that correct?
- which rule is invoked in this resolution? (reference to standard great, but a helpful brief summary appreciated)
Notes:
I tried to google for it, but old hits I got on SO were cases for other overload resolutions involving const. However, link to an old SO actually explaining the above obviously great.
This came up when re-reading Stroustrup's "The C++ programming language", 2nd edition ("Special Edition"), String/Cref example in section 11.12, p. 296. As Stroustrup is so precise, the answer might be in previous sections, but I fail to see where. Reference to sections in Stroustrup very welcome too (2nd edition best as this is the one I have). Section 10.2.6 introduces const members as those "that don't change an object's value", which hints at the answer, but doesn't strike me as a clear resolution directive.
In N3242 (the standard draft I have on hand), 13.3.1 paragraph 4 says
the type of the implicit object parameter is "lvalue reference to cv X” for [non-static member] functions declared without a
ref-qualifier or with the & ref-qualifier
this means that type of the implicit object argument, which occurs first, is an "lvalue reference to cv X
", where X
is the class, and cv
is the cv-qualification of the member variable (i.e. const or non-const). Then, overload resolution continues as normal.
To review the overload resolution process, first, both are listed as "candidate" functions as they are in the correct scope and have the correct name.
In the const
case, only the const
member function gets to the next step (called "viability"), so it's automatically the best choice. The non-const member function is not viable because you can't convert a const
reference into a non-const reference.
In the non-const case, both the const and non-const versions are viable, but the non-const one is "better" because of the fifth rule of 13.3.3.2 paragraph 3, quoted below.
Standard conversion sequence S1 is a better conversion sequence than
standard conversion sequence S2 if ...
S1 and S2 are reference bindings, and the types to which the
references refer are the same type except for top-level cv-qualifiers,
and the type to which the reference initialized by S2 refers is more
cv-qualified than the type to which the reference initialized by S1
refers.