2013-12-14 1 views
4

나는이 코드를 가지고있다.템플릿 함수 정의

일부 템플릿 함수 정의를 일부 유형에 사용할 수 없다면 컴파일러는 자동으로 무시하고 다른 정의를 시도 할 것이라고 생각했습니다. 틀렸어?

Clang 3.3은 정상적으로 컴파일되고 예상대로 작동합니다. GCC 4.9 그러나이 오류가 throw됩니다 :

mathutils.hpp:77:6: error: redefinition of 'template<class T1, class T2> decltype (prod(a, b)) operator*(const T1&, const T2&)' 
auto operator*(const T1& a, const T2& b) -> decltype(prod(a, b)) { 
    ^
mathutils.hpp:72:6: note: 'template<class T1, class T2> decltype (viennacl::linalg::prod(a, b)) operator*(const T1&, const T2&)' previously declared here 
auto operator*(const T1& a, const T2& b) -> decltype(viennacl::linalg::prod(a, b)) { 
    ^

그래서 어떤 컴파일러가 잘못 되었습니까?

그리고 가능한 해결 방법은 무엇입니까? (내가하고 싶은 것을 취소되지 않은 경우 :. 나는 그것이 하나 그 중 하나가 구현을 제공에 따라 viennacl::linalg::prod 또는 prod, 사용하도록 operator*을 구현하려는)


작은 자체에 포함 된 테스트 케이스를 :

namespace X { 
    template<typename T> struct Mat{}; 
    template<typename T> struct MatExpr {}; 

    template<typename T> 
    MatExpr<T> prod(Mat<T> const& A, Mat<T> const& B) { return MatExpr<T>(); } 
}; 

struct Mat2 {}; 

template<typename T> 
X::Mat<T> prod(X::Mat<T> const& A, Mat2 const& B) { return X::Mat<T>(); } 


template<typename T1, typename T2> 
auto operator*(const T1& a, const T2& b) -> decltype(X::prod(a, b)) { 
    return X::prod(a, b); 
} 

template<typename T1, typename T2> 
auto operator*(const T1& a, const T2& b) -> decltype(prod(a, b)) { 
    return prod(a, b); 
} 



int main() {} 

GCC here의 버그로 업 스트림을보고했습니다.

+0

동일한 T1 및 T2의 경우 두 개의 decltype에서 제공 한 정확한 유형은 무엇입니까? 그들이 동일하면, 나는 당신이 가진 것처럼 메시지를 줄 것으로 기대합니다. – polkadotcadaver

+0

'prod'와'viennacl :: linalg :: prod'는 둘 다 작동하지 않을 것입니다. 항상 첫 번째 또는 후자입니다. 두 경우 모두 decltype이 결코 정의되지 않는다는 것입니다. 또한 사용시 오류가 발생하지 않으며 컴파일러가 정의를 구문 분석 할 때 오류가 이미 발생합니다. – Albert

+2

SSCCE 변경 사항이 있습니까? – jrok

답변

0

gcc가 옳은지 여부에 관계없이 나중에 표준에 관련된 절을 인용 할 것입니다. 한편, 여기 당신이 시도 할 수있는 해결 방법입니다 : 내가 위에서 한 그것의 인스턴스를해야 정확히 prod 알 수 있도록 명시 적으로 템플릿 인수를 지정하는 것입니다 무엇

template<typename T1, typename T2> 
auto operator *(const T1 &a, 
       const T2 &b) -> decltype(::prod<typename T1::value_type>(a, b)) 

. 또 다른 미묘한 점은 ADL이 명시 적으로 전역 적으로 자격을 부여 받아야한다는 것이 었습니다. 이 없으면 컴파일러는 anamespace X의 형식임을 알게되고 X::prod::prod 둘 다 모호 할 것입니다.

마지막으로, X::Mat에 약간의 변화는 그래서 우리는 그 형태 T을 참조 할 수 있습니다 :

namespace X 
{ 
    template<typename T> struct Mat { typedef T value_type; }; 
    // ... 

가 여기 working test example입니다.