Объявление друга шаблонного оператора * с оператором-членом *

Прикрепленный к этому вопросу код не компилируется (g++ 4.7) со следующими ошибками:

test.cpp:22:31: error: declaration of ‘operator*’ as non-function
test.cpp:22:31: error: expected ‘;’ at end of member declaration
test.cpp:22:32: error: expected unqualified-id before ‘<’ token
test.cpp: In function ‘int main(int, char**)’:
test.cpp:39:11: warning: unused variable ‘d’ [-Wunused-variable]
test.cpp: In instantiation of ‘Vector3<T> operator*(T, const Vector3<T>&) [with T = float]’:
test.cpp:37:16:   required from here
test.cpp:25:10: error: ‘float Vector3<float>::v [3]’ is private
test.cpp:30:57: error: within this context
test.cpp:25:10: error: ‘float Vector3<float>::v [3]’ is private
test.cpp:30:57: error: within this context
test.cpp:25:10: error: ‘float Vector3<float>::v [3]’ is private
test.cpp:30:57: error: within this context

Однако, если объявление друга перемещено до operator* объявление / определение члена (просто поменяйте местами комментарии в примере кода), затем все будет хорошо. Я не понимаю почему. Есть ли способ заставить этот код скомпилироваться с объявлением друга, расположенным после operator* декларация участника?

template<typename T>
class Vector3;

template<typename T>
Vector3<T> operator*(T f, const Vector3<T>& v);

template<typename T>
class Vector3 {
public:
    Vector3(T x, T y, T z) {
        v[0] = x;
        v[1] = y;
        v[2] = z;
    }

  //friend Vector3<T> operator*<>(T f, const Vector3<T>& v); // WORKS

    T operator*(const Vector3<T>& other) const {
        return (v[0] * other.v[0] + v[1] * other.v[1] + v[2] * other.v[2]);
    }

    friend Vector3<T> operator*<>(T f, const Vector3<T>& v); // FAILS

private:
    T v[3];
};

template<typename T>
Vector3<T> operator*(T f, const Vector3<T>& v) {
    return Vector3<T>(f * v.v[0], f * v.v[1], f * v.v[2]);
}

int main(int argc, char *argv[]) {
    Vector3<float> v(0, 0, 0);
    Vector3<float> w(0, 0, 0);

    w = 2.0f * v;

    float d = v * w;

    return 0;
}

1 ответ

Проблема заключалась в том, что вы не указали, что имеете в виду operator* из глобального пространства имен, для этого измените объявление своего друга на:

friend Vector3<T> (::operator*<>)(T f, const Vector3<T>& v);

Когда вы объявили об этом перед оператором * member, не было никакой двусмысленности, поэтому она была правильно подобрана.

Другие вопросы по тегам