Search code examples
c++templatesoperator-overloadingmember-functionsclass-template

No match to call for template member function for operator<< overload


I am trying to write an output function for a matrix class by overloading the operator<< overload. The matrix class also has an indexing function, which is created by overloading the `op.

The code is as follows:

template<typename T, unsigned int N>
T& LU_Matrix<T, N>::operator() (unsigned int i, unsigned int j)
{
    return data_[N * i + j];
}

template<typename T, unsigned int N>
std::ostream& operator<< (std::ostream& os, const LU_Matrix<T, N> mat)
{
    for (unsigned int i = 0; i < N; ++i)
    {
        for (unsigned int j = 0; j < N; ++j)
        {
            os << mat(i, j) << " ";
        }
        os << std::endl;
    }
    return os;
}

int main()
{
    LU_Matrix<double, 3> lu_mat();
    // instantiate lu_mat here
    std::cout << lu_mat << std::endl;
    return 0;
}

When I run this, it throws the error

no match to call for '(const LU_Matrix<double, 3>) (unsigned int, unsigned int)'

It seems like the compiler should have created the stated function, given the templated function overloading operator<<. What's going wrong here?


Solution

  • What's going wrong here?

    As others have pointed out in comment section, Your LU_Matrix::operator() isn't const-qualified, therefore it cannot be used with const qualified LU_Matrix objects.

    In your operator<< overload, you have the above-mentioned case:

    std::ostream& operator<< (std::ostream& os, const LU_Matrix<T, N> mat)
    //                                          ^^^^^^ --------------------> this
    

    Here the compiler does not find a const operator() operator overload to call with the const object, hence the error!

    You need to change the declaration and definition to:

    const T& operator() (unsigned int i, unsigned int j) const;
    ^^^^^^^^^                                            ^^^^^^
    

    Not that, the return parameter also must be const qualified, as you return the element from a member of the class from a const member function.


    In addition, as an improvement operator<<, neither modify the object nor require a copy, therefore you can actually pass const-ref to LU_Matrix<T, N> to the operator<< overload:

    template<typename T, unsigned int N>
    std::ostream& operator<< (std::ostream& os, const LU_Matrix<T, N>& mat) /* noexcept */
    {
        // ...
        return os;
    }
    

    (See a demo)