2014-01-19 89 views
1

连接到这个问题的代码编译失败(克++ 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; 
} 

回答

2

的问题是,你没有指定你的意思是从全局命名空间的operator *,要做到这一点您的朋友声明更改为:

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

当你面前的operator *成员宣布它有没有歧义,所以它被正确地拾起。

+0

谢谢,现在编译。但是,成员'operator *'声明如何来自全局名称空间的'operator *'映射? – user3146587

+0

更新应该澄清。 – tumdum

+0

@Tomasz:这个规则实际上并没有。全局命名空间不是“最内层非封闭非类作用域之外”,它*是最内层封闭非类作用域。这就是为什么它可以在所有被发现(如果没有本地运营商'*') –