Why is my class using the wrong operator()?

Consider the following class Foo which provides 2 operators (), one for reading and another one for writing.

#include <iostream>
#include <vector>

template <typename T>
class Foo {
  Foo(const std::vector<T> &values) { vals = values; }
  const T &operator()(const int i, const int j) const {
    std::cout << "Read" << std::endl;
    return vals[i];
  T &operator()(const int i, const int j) {
    std::cout << "Write" << std::endl;
    return vals[i];

  std::vector<T> vals;

int main() {
  std::vector<int> values(100, 1);

  Foo<int> f{values};
  f(1,1) = 42; //here it writes:OK
  std::cout << f(1,1) << std::endl; //why is again the "read" version called?
  return 0;

I am not able to understand why only the "write" version is called in my code.


  • The problem is that f is non-const, which means that the non-const member function version is a better match than the const member function version since the type of this parameter for non-const version is Foo<int>* while for the const version it is const Foo<int>* and so the latter requires a qualification conversion while the former does not and hence a better match.

    To solve this you can either make f const(but then you won't be able to write on it) or use const_cast on the non-const f as shown below:

    int main() 
         std::vector<int> values(100, 1);
         Foo<int> f{values};  //non-const f
         f(1,1) = 42; //uses write version
         //use read version now as we've used const_cast
         std::cout << const_cast<const Foo<int>&>(f)(1, 1) << '\n'; //use const_cast 
         return 0;

    Working demo

    With C++17 you can also use std::as_const as shown in this demo.