I have a struct with these operators (given some type T):
T& operator[](size_t i) { return write(i); }
const T& operator[](size_t i) const { return get(i); }
When I access a non-const object of this by [i], will it always use the non-const operator[] or will it automatically see which one is needed (e.g. if the const-version is “enough”) and take that one? What are the rules there? And do most compilers (I mostly care about Clang, recent GCC and recent MSVC) behave the same there?
Background: write(i) could be much more costly than get(i). I even have some code where the behavior is slightly different, where write(i) might touch some files, set some modified-flags or whatever.
As with any member function, the choice of overload depends on the type of the implicit instance argument:
In case #1, the implicit instance argument has type
T, so the overloadT::foo()is viable and will be selected. In case #2, the implicit instance argument has typeT const, and thus only an overloadT::foo() constis viable, and will be selected if it exists.The normal overload resolution rules are at play here: If you have both const and non-const overloads and the instance argument is non-constant, then the non-constant version is chosen because it requires zero conversions, while the const overload would require one (standard) conversion, namely from
T &toT const &, and thus that overload is not as good a fit as the non-const one.