2013-06-13 3 views
1

이 링크 오류를 이해할 수 없습니다. 는 I 2 개 클래스 가지고이 링크 오류를 이해할 수 없습니다.

#include "Vector3.h" 
#include "Quaternion.h" 

template<typename T> 
class Point3 final 
{ 
public: 
    constexpr Point3(const Vector3<T>& vec) 
    : x(vec.x), y(vec.y), z(vec.z) 
    {} 

    constexpr operator const Vector3<T>() const 
    { 
     // It is the equivalent of Vector3 = Point3 - Origin 
     return Vector3<T>(x, y, z); 
    } 

    constexpr operator Vector3<T>() const 
    { 
    // It is the equivalent of Vector3 = Point3 - Origin 
    return Vector3<T>(x, y, z); 
    } 

    T x = T(0); 
    T y = T(0); 
    T z = T(0); 

    friend Vector3<T>; 
    friend Quaternion<T>; 

    friend Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs); 
    friend Vector3<T> operator*(Vector3<T> lhs, const Vector3<T>& rhs); 
}; 

typedef Point3<Float32> Point3f; 

I 또한 상세히 내가 믿지 무관 쿼터니온 클래스가
template<typename T> 
class Vector3 final 
{ 
public: 

    constexpr Vector3() 
    {} 

    constexpr Vector3(T _x, T _y, T _z) 
    : x(_x), y(_y), z(_z) 
    {} 

    T x = T(0); 
    T y = T(0); 
    T z = T(0); 

}; 

typedef Vector3<Float32> Vector3f; 

을하지만,이 클래스는 비 멤버 연산자 * 가지고

template<typename T> 
Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs) 
{ 
    // nVidia SDK implementation 
    Vector3<T> qvec(lhs.x, lhs.y, lhs.z); 
    Vector3<T> uv = cross(qvec, rhs) * T(2.0) * lhs.w; //uv = qvec^v; 
    Vector3<T> uuv = cross(qvec, uv) * T(2.0); //uuv = qvec^uv; 
    return rhs + uv + uuv; 
} 

을 이제이 라인은 링크 오류를 발생 시키지만 왜 그럴까요? 여기

Math::Point3<Float32> pt = -Math::Point3<Float32>::UNIT_Z; 
Math::Vector3<Float32> vec = orientation_*pt; // link error here (orientation is a Quaternion<Float32>) 
//Math::Vector3<Float32> vec = orientation_*Math::Vector3<Float32>(pt); // this solve the link error. 

링크 오류

Undefined symbols for architecture x86_64: 
    Math::operator*(Math::Quaternion<float> const&, Math::Vector3<float> const&), referenced from: 
    GfxObject::Procedural::BoxGenerator::addToTriangleBuffer(GfxObject::Procedural::TriangleBuffer&) const in ProceduralBoxGenerator.o 

업데이트

나는이 정말 가까이하지만 문제가 차이 의존이 질문을 발견합니다. 에서

: question 1question 2

하지만 내 경우에는 내가 2 개 템플릿 클래스 대신 같은 클래스 만 2 instantions 사이의 변환이 필요 . 이게 도움이되기를 바랍니다!

friend Vector3<T> operator* <> (const Quaternion<T>& lhs, const Vector3<T>& rhs); 

이 일반적인 실수는 C++ FAQ here에 설명되어 있습니다 : 확인하는

+2

당신은 ** 두 가지 클래스와 Quaternion 클래스를 가지고 있지 않습니다 **. 3 개의 ** 템플릿 **이 있습니다. –

+0

템플릿 화 된'operator *'를 적어도 하나 이상 인스턴스화해야합니다. 그것은 소스 파일에 포함 된 헤더 파일에 포함되거나'operator * '를 포함하는 소스 파일에서 명시 적으로 인스턴스화되어야합니다. –

+0

@PeteBecker 예 3 개의 템플릿 클래스가 있습니다. 그러나 나는이 문제가 2 개의 템플릿 클래스 인 Vector3와 Point3에서 발생한다고 믿습니다. – monamimani

답변

1

봅니다 컴파일러는 당신의 친구 선언이 템플릿 특수화가 아닌 새로운 템플릿이 아닌 함수의 선언이 있어야하는데 알고 .

0

SSCCE 시작 :

template<typename T> class Quaternion { }; 
template<typename T> class Vector3 { }; 
template<typename T> class Point3 { 
public: 
    operator Vector3<T>() const { return Vector3<T>(); } 
    friend Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs); 
}; 
template<typename T> 
Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs) { } 
int main() { 
    Quaternion<float> orientation_; 
    Point3<float> pt; 
    Vector3<float> vec = orientation_*pt; 
    return 0; 
} 

GCC 4.7 나는 다음과 같은 얻을 컴파일 :

x.cc:6:79: warning: friend declaration ‘Vector3<T> operator*(const Quaternion<T>&, 
        const Vector3<T>&)’ declares a non-template function 
        [-Wnon-template-friend] 
x.cc:6:79: note: (if this is not what you intended, make sure the function template 
       has already been declared and add <> after the function name here) 
Undefined symbols for architecture x86_64: 
    "operator*(Quaternion<float> const&, Vector3<float> const&)", referenced from: 
     _main in ccKgI7Ru.o 

이 문제를 지적한다 : 당신은 친구에게 기능 아닌 선언된다 친구 템플릿. 확인 템플릿 선언 preceedes 우정 라인을 만들고, 꺾쇠 괄호 추가 :이 문제를 해결하려면 두 가지 작업을 수행해야

template<typename T> 
Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs) { } 

template<typename T> class Point3 { 
public: 
    operator Vector3<T>() const { return Vector3<T>(); } 
    friend Vector3<T> operator*<>(const Quaternion<T>& lhs, const Vector3<T>& rhs); 
}; 

이 컴파일러 오류로 링커 오류를 설정합니다 :

error: no match for ‘operator*’ in ‘orientation_ * pt’ 
note: candidate is: 
note: template<class T> Vector3<T> operator*(const Quaternion<T>&, const Vector3<T>&) 
note: template argument deduction/substitution failed: 
note: ‘Point3<float>’ is not derived from ‘const Vector3<T>’ 

어느 것이 합리적인지 : 친구 선언은 누가 어떤 데이터에 액세스 할 수 있는지에 대한 성명서입니다. 템플릿 분석을위한 자동 유형 변환에서 조금 도움이되지 않습니다. 그래서 대신에 다음과 같은 제안 :

template<typename T> class Point3 { 
public: 
    operator Vector3<T>() const { return Vector3<T>(); } 
    friend Vector3<T> operator*(const Quaternion<T>& lhs, const Point3& rhs) { 
    return lhs * Vector3<T>(rhs); 
    } 
}; 

이 명시 적으로 의도했던 캐스트를 수행하는 새로운 인라인 친구 연산자를 선언합니다.

+0

SSCCE에서 보여준 것을 알려줘서 고마워. 네가봤을 때까지 정말 맨손으로 보였다. 실제로 어떻게 작동시키는 지 발견했습니다.나는 결국 해결책을 좋아하지 않지만 효과적인 C++의 46 번 항목과 같이 내가 습득하려고 시도한 것입니다. – monamimani

0

사실 내가 작동하게하려면 Point 클래스에서 함수를 선언 한 친구에게 시체를 주어야합니다. Scott Meyers의 Effective C++ (제 3 판)의 46 번 항목처럼하고 싶었습니다. 이 질문 에서처럼 link.

핵심은 내부에 함수가 있어야한다는 것입니다. 그래서 클래스 POINT3 이제 MVG가 그랬던 것처럼 나는 몇 가지 쓸모없는 코드를 제거 한 감사합니다.

template<typename T> class Point3 { 
public: 
    operator Vector3<T>() const { return Vector3<T>(); } 
    friend Vector3<T> operator*(const Quaternion<T>& lhs, const Vector3<T>& rhs) 
    { 
    return lhs*rhs; 
    } 
}; 

이 모든 것을 컴파일 할 링크. 좌를 우는 즉 (Quaternion.h에 정의 된 연산자를 호출합니다 (이 될 포인트 3의 헤더 파일에 포함).

내가 왜 중복 된 기호가 없는지입니다. 내게 친구 연산자 * PointManager 클래스 및 연산자 * Quaternion.h에 정의 된 헤더 파일은 동일한 서명이지만 컴파일 및 링크됩니다.

관련 문제