1

I have a templated class Matrix:

    template<typename T>
    class Matrix {
        //blah-blah-blah
        }

And the following operator:

template<typename T>
bool operator==(const Matrixes::Matrix<T> &lhs, const Matrixes::Matrix<T> &rhs) {
    if (lhs.get_cols()!=rhs.get_cols() || lhs.get_rows()!=rhs.get_rows()){
        return false;
    }
    for (int r = 0; r < lhs.get_rows(); ++r) {
        for (int c = 0; c < lhs.get_cols(); ++c) {
            if (lhs.get(r, c) != rhs.get(r, c)) {
                return false;
            }
        }

    }
    return true;
}

The aforementioned operator is defined outside the Matrixes namespace.

I have a few tests(I am using framework Google Tests). However, if I write something like:

TEST(MatrixOperations, MatrixMultiplicationSimple) {
    Matrixes::Primitives<int>::VectorMatrix vec1{{{8, 3, 5, 3, 8}, {5, 2, 0, 5, 8}, {0, 3, 8, 8, 1}, {3, 0, 0, 5, 0}, {2, 7, 5, 9, 0}}};
    Matrixes::Primitives<int>::VectorMatrix vec2{{{3, 1, 7, 2, 9}, {4, 6, 2, 4, 5}, {2, 5, 9, 4, 6}, {5, 3, 3, 1, 2}, {1, 8, 2, 6, 8}}};
    Matrixes::Matrix<int> vec1m{vec1};
    Matrixes::Matrix<int> vec2m{vec2};
    Matrixes::Matrix<int> matrix_out_ref{{{69, 124, 132, 99, 187}, {56, 96, 70, 71, 129}, {69, 90, 104, 58, 87}, {34, 18, 36, 11, 37}, {89, 96, 100, 61, 101}}};
    Matrixes::Matrix<int> matrix_out_fact = vec1m * vec2m;
    bool t = matrix_out_fact == matrix_out_ref;
    EXPECT_EQ(t, true);
}

everything works fine. Note, that I'm using operator== "manually" here:

 bool t = matrix_out_fact == matrix_out_ref;
 EXPECT_EQ(t, true);

However, if instead of these two lines I write something like:

EXPECT_EQ(matrix_ou_fact, matrix_out_ref);

I get the compilation error:

/usr/local/include/gtest/gtest.h:1522:11: error: no match for ‘operator==’ (operand types are ‘const Matrixes::Matrix<int>’ and ‘const Matrixes::Matrix<int>’)
   if (lhs == rhs) {

Why doesn't gtest "see" the definition of operator==?

Thanks

drsealks
  • 2,282
  • 1
  • 17
  • 34
  • 1
    Put the operator in the same namespace as the class, to give argument-dependent lookup a chance. Otherwise, it won't be found by name lookup under many circumstances. – Igor Tandetnik Mar 17 '19 at 14:44
  • @IgorTandetnik indeed it works if I put it under the same namespace. Do you want to write a separate answer so that i could accept it? Also, what topic should I familiarise myself with to better understand what has happened? Thanks – drsealks Mar 17 '19 at 14:46
  • Read about "name lookup" – Igor Tandetnik Mar 17 '19 at 14:51

1 Answers1

4

The comparison inside EXPECT_EQ happens in a different scope than your immediate test case. It looks up the operator function it needs to call via argument dependent lookup(ADL). Because your operator function is not in the same namespace as your class, it is not picked up by ADL.

It works inside your immediate test case because you probably include the appropriate headers in the appropriate order, so that finding the operator does not rely on ADL. But the implementation of the Gtest framework has to rely on ADL.

So the fix is easy. Move your custom operator into the Matrixes namespace. It's part of your class's public interface, so it belongs in the same namespace anyway.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458