2014-02-05 2 views
1

클래스 템플릿의 (다른) 특수화 인스턴스를 두 개 가져 와서 컴파일 타임에 템플릿 전문화에서 추론 한 값을 반환하는 메서드를 만들려고합니다. 내가 지금까지 무엇을 가지고friend 메서드의 인수 목록에 다른 템플릿 전문화

내가 field 값을 공개 할 때까지 (GCC에 의해)

#include <iostream> 
#include <utility> 

template<typename T> class box 
{ 
protected: 
    T value; 
public: 
    box(T value) 
    { 
     this->value = value; 
    } 
    friend std::ostream& operator<<(std::ostream& os, box<T>& obj) 
    { 
     return os << obj.value; 
    } 

    template<typename K> friend auto operator+(
     const box<T>& left, const box<K>& right) -> 
      box<decltype(std::declval<T>() + std::declval<K>())> 
    { 
     typedef decltype(std::declval<T>() + std::declval<K>()) result_type; 
     return box<result_type>(left.value + right.value); 
    } 
}; 

int main() 
{ 
    box<int> int_container = box<int>(2); 
    box<float> float_container = box<float>(7.0); 
    auto another_one = int_container + float_container; 
    std::cout << int_container << " " << float_container << " " << another_one << std::endl; 
} 

이 컴파일되지 않습니다 (최소한의 경우)입니다. 컴파일러는 신고 된 운영자와 친구로 container<K>을 (또는) 처리 할 수 ​​없다고 생각합니다.

물론 value에 공용 getter를 추가 할 수 있습니다.

다른 해결책은 template<typename> friend class box;을 클래스 정의의 시작 부분에 추가하고 연산자를 friend 대신 클래스 멤버로 만들어서이 템플릿의 모든 특수화를 만드는 것입니다. 그러나 그러한 대안이 존재하지 않는 friend 메소드를 작성하기로 결정한 경우 해당 접근법이 작동하지 않습니다. (연산자를 클래스 멤버로 다시 정의하지 않고 모든 전문화 친구를 만들면 원래의 경우와 같은 이유로 컴파일되지 않습니다.)

그래서 메소드 템플릿을 모든 템플릿 매개 변수가 인수의 형식 정의 중 하나에서 사용되는 경우 클래스 템플릿의 전문화가 필요합니까?

답변

1

모든 운영자는 모든 템플릿 전문 분야의 친구 여야하기 때문에 두 템플릿 매개 변수를 모두 자유롭게 유지해야합니다. 대신 성가신 auto -> decltype 건축, 당신은 또한 간단하고 읽기 쉽게 사용할 수있는 방법으로

template <typename T> 
class box 
{ 
    // ... 

    template <typename A, typename B> 
    friend 
    auto operator+(const box<A>& left, const box<B>& right) -> box<decltype(std::declval<A>() + std::declval<B>())>; 
}; 

template <typename A, typename B> 
auto operator+(const box<A>& left, const box<B>& right) -> box<decltype(std::declval<A>() + std::declval<B>())> 
{ 
    return { left.value + right.value }; 
} 

: 나는 또한 내가 왜 완벽하게 잘 모르겠어요하지만 당신이, 클래스 외부에 정의를 이동해야하는 것을 발견 box<typename std::common_type<A, B>::type> 또는 C++ 14 box<std::common_type_t<A, B>>.

+0

감사합니다. 아직도, 나는'std :: common_type :: type'이이 경우에 필요하지 않다고 믿는다. 왜냐하면 타입은 피연산자의 타입이 아니라 추론 된 결과로부터 유추되어야하기 때문이다. –

+0

@MaxKibardin : 네 말이 맞아서,'+'연산자가 오버로드되어 완전히 다른 결과를 낼 수있다. –