Какая функция вызывается, зависит от того, является ли экземпляр константным или нет. Первая версия позволяет изменить экземпляр:
Matrix<int> matrix;
matrix(0, 0) = 10;
Перегрузка const разрешает доступ только для чтения, если у вас есть экземпляр const (ссылка) Matrix:
void foo(const Matrix<int>& m)
{
int i = m(0, 0);
//...
//m(1, 2) = 4; //won't compile
}
Второй не возвращает ссылку, поскольку намерение состоит в том, чтобы запретить изменение объекта (вы получаете копию значения и, следовательно, не можете изменить экземпляр матрицы).
Здесь T должен быть простым числовым типом, который является дешевым (er) для возврата по значению. Если T также может быть более сложным определяемым пользователем типом, было бы также обычным для const-перегрузок возвращать ссылку на const:
template <class T>
class MyContainer
{
//..,
T& operator[](size_t);
const T& operator[](size_t) const;
}