Pregunta

I have been trying to get the following code work from the book "The C++ Programming Language (4th Edition)" section "23.4.7 Friends" but could not succeed.

template<typename T> class Matrix;

template<typename T>
class Vector {
    T v[4];
public:
    friend Vector operator*<>(const Matrix<T>&, const Vector&); /* line 7 */
    // ...
};

template<typename T>
class Matrix {
    Vector<T> v[4];
public:
    friend Vector<T> operator*<>(const Matrix&, const Vector<T>&); /* line 14 */
    // ...
};

template<typename T>
Vector<T> operator*(const Matrix<T>& m, const Vector<T>& v)
{
    Vector<T> r;
    // ... m.v[i] and v.v[i] for direct access to elements ...
    return r;
}

Here is a sample usage for the above API:

int main() {
    Matrix<int> lhs;
    Vector<int> rhs;
    Vector<int> r = lhs * rhs;

    return 0;
}

g++ with version:

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3

gave the following output:

test.cpp:7: error: declaration of ‘operator*’ as non-function
test.cpp:7: error: expected ‘;’ before ‘<’ token
test.cpp:14: error: declaration of ‘operator*’ as non-function
test.cpp:14: error: expected ‘;’ before ‘<’ token

and clang with version:

Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

gave the following output:

test2.cpp:7:19: error: friends can only be classes or functions
    friend Vector operator*<>(const Matrix<T>&, const Vector&);
                  ^
test2.cpp:7:28: error: expected ';' at end of declaration list
    friend Vector operator*<>(const Matrix<T>&, const Vector&);
                           ^
                       ;
test2.cpp:14:22: error: friends can only be classes or functions
    friend Vector<T> operator*<>(const Matrix&, const Vector<T>&);
                     ^
test2.cpp:14:31: error: expected ';' at end of declaration list
    friend Vector<T> operator*<>(const Matrix&, const Vector<T>&);
                              ^
                              ;
4 errors generated.

The book says:

The <> after the name of the firend function is needed to make clear that the friend is a template function.

I could not spot the problem in the code, can you?

¿Fue útil?

Solución

Yes, it's a bug in the book.

The function template must already be visible at that point, otherwise it cannot be instantiated to produce the overload you're trying to befriend.

So, moving the operator definitions above that of Vector (which in itself requires that we provide a forward declaration) solves the problem.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top