2010-05-05 12 views
1

하위 유형을 정의하는 템플릿 클래스가 있습니다. 이진 코드 operator+을 템플릿 함수로 정의하려고하지만 컴파일러에서 operator+의 템플릿 버전을 확인할 수 없습니다.연산자 클래스 + 하위 클래스 용

#include <iostream> 
template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    struct subtype { subtype(other_type v) : val(v) {} other_type val; } cs; 
}; 

template<typename other_type> 
typename c<other_type>::subtype operator+(const typename c<other_type>::subtype& left, 
         const typename c<other_type>::subtype& right) 
{ return typename c<other_type>::subtype(left.val + right.val); } 

// This one works 
// c<int>::subtype operator+(const c<int>::subtype& left, 
//   const c<int>::subtype& right) 
// { return c<int>::subtype(left.val + right.val); } 

int main() 
{ 
    c<int> c1 = 1; 
    c<int> c2 = 2; 
    c<int>::subtype cs3 = c1.cs + c2.cs; 
    std::cerr << cs3.val << std::endl; 
} 

가 나는 operator+<int> 대신 operator+ 검색 그래서 컴파일러 (g ++ 4.3) 템플릿 유형을 추측 할 수 없기 때문에 이유라고 생각합니다.

그 이유는 무엇입니까? 어떤 우아한 해결책을 제안 할 수 있습니까?

+0

에 코드를 변경할 수는 C++ 표준 14.8.2.4/4에 따라 여기 문맥을 nondeduced 점이다. –

답변

4

귀하의 의혹이 맞습니다. 컴파일러는 other_type이 무엇인지 알지 못합니다. 그것은 논증에서 그것을 추론 할 수 없다. 이러한 양식은 종종 필요한 정보를 제공하기에는 너무 느슨합니다. 당신이 int을 통과한다면 그들 모두가 유형 int을 가지고 있기 때문에 다음 c<T>의 법안에 딱 맞는,

template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    typedef int subtype; 
}; 

을 고려하십시오. 중첩 된 클래스의 특정 경우에는 가능할 수도 있지만 고유하지는 않습니다. 당신이 typedef c<int> subtype;을 넣을 수있는 c<float>에서, c<float>::subtypec<int>::subtype이 모두 청구서에 부합한다고 상상해보십시오.

이전 표준 시간으로 되돌아 가면 John Spicer가 수행 한 템플릿 문제 목록이 존재하며 합리적인 해결책을 고안했습니다. 그것은 그러한 문제 중 하나 였고, 문제의 가치가 없다는 것이 발견되었습니다. 항상 명시 적으로 인수를 제공해야합니다. 이는 결코 추론되지 않습니다.

당신은 이유는이

template<typename other_type> 
struct subtype { 
    subtype(other_type v) : val(v) {} 
    other_type val; 
}; 

template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    subtype<other_type> cs; 
}; 

template<typename other_type> 
subtype<other_type> operator+(const subtype<other_type>& left, 
         const subtype<other_type>& right) 
{ return subtype<other_type>(left.val + right.val); } 

에 또는이

template<typename other_type> 
struct c { 
    c(other_type v) : cs(v) {} 
    struct subtype { 
    subtype(other_type v) : val(v) {} other_type val; 

    /* note: don't forget friend! */ 
    friend subtype operator+(const subtype& left, 
         const subtype& right) 
    { return subtype(left.val + right.val); } 
    } cs; 
}; 
+0

+1 그걸 두들겨 패; 이것은 내 것이 어쨌든 될 것보다 낫다. –

+0

@Charles, 고마워. –

+0

두 번째는 오류 (shadowing other_type)를보고 템플릿 유형의 이름을 변경하면 이전과 같은 오류가 발생합니다 (이 친구 연산자의 유형 +가 원본과 동일해야 함). – baol