2013-07-26 2 views
2
template <class T> 
class Foo { 
public: 
    T val; 
    Foo(T _v): val(_v){} 
    friend ostream& operator<< (ostream& out, const Foo& A) { 
     out << A.val; 
     return out; 
    } 
}; 

template <class X, class Y> Foo<???> operator+(const Foo<X>& A, const Foo<Y> & B) { 
    if (sizeof(X) > sizeof (Y)) 
     return Foo<X>(A.val + B.val); 
    else 
     return Foo<Y>(A.val + B.val); 
} 

int main() { 
    Foo<double> a(1.5); 
    Foo<int> b(2); 
    cout << a << endl; 
    cout << b << endl; 
    cout << a+b << endl; 
} 

내 목표는 operator+ 함수가 인수의 유형에 따라 다른 유형을 반환하도록하는 것입니다. 예를 들어C++ 템플릿 자동 유형 프로모션

, aint이고 하나 또는 둘 다이다 double 다음 Foo<double>을 리턴하는 경우, b는, ​​다음 Foo<int>int을 반환 경우.

할 수 있습니까?

+1

아래의 의견에 대 한 응답에서, 나는 태그 C++ 03에 추가 : 다음은 자신의 규칙을 부여 할 경우 방법입니다. 당신이 무언가의 현재가 아닌 버전을 추적 할 때 당신은 당신의 질문에 그 것을 기술해야합니다. –

답변

3

사용 부분 템플릿 특수화 (C++ 03 또는 C++ 11).

// C++ does not allow partial specialization of function templates, 
// so we're using a class template here. 

template <typename X, typename Y, bool xLarger> 
struct DoPlusImpl // When x is selected 
{ 
    typedef Foo<X> result_type; 
}; 

template <typename X, typename Y> 
struct DoPlusImpl<X, Y, false> // When y is selected 
{ 
    typedef Foo<Y> result_type; 
}; 

template <typename X, typename Y> // Select X or Y based on their size. 
struct DoPlus : public DoPlusImpl<X, Y, (sizeof (X) > sizeof (Y))> 
{}; 

// Use template metafunction "DoPlus" to figure out what the type should be. 
// (Note no runtime check of sizes, even in nonoptimized builds!) 
template <class X, class Y> 
typename DoPlus<X, Y>::result_type operator+(const Foo<X>& A, const Foo<Y> & B) { 
    return typename DoPlus<X, Y>::result_type 
     (A.val + B.val); 
} 

현재 IDEOne에 대한 조치에서 볼 수 있습니다 ->http://ideone.com/5YE3dg

+0

'오류 : ISO C++은 타입이없는 'operator +'선언을 금지 [0123] –

+0

@Tran : 이것이 유효 함을 확인했습니다. 후행 반환은 일부 종류의 decltype 시나리오에만 필요합니다. 이것은 당신이 원하는 것을해야합니다. –

+0

@Tran : 샘플 클래스로 작업하는 IDEOne 예제를 추가했습니다. –

4

(C++ 11) dectype 내부 declval 식을 사용이 가능

#include <utility> 

template <class X, class Y> 
Foo<decltype(std::declval<X>() + std::declval<Y>())> operator+(...); 
+0

컴파일러는 다음과 같이 말합니다 :' 'common_type'네임 스페이스 'std'의 이름이 타입이 아니며'error : 템플릿 인자 1이 유효하지 않습니다. ' –

+0

@TranSonHai 편집을했습니다. – 0x499602D2

+0

이번에는'error : 'declval'이 'std'의 멤버가 아니며 'error : 템플릿 인자 1이 유효하지 않습니다.' –

1

예!

template <typename X, typename Y> struct Rule {}; 
template<> struct Rule<int, int> { typedef int type;}; 
template<> struct Rule<float, int> { typedef bool type;}; 

그런 다음

template <class X, class Y> Foo<typename Rule<X, Y>::type> operator+(...) 
+0

좀 더 일반화 할 수 있을까요?, Foo가 int, double, float뿐만 아니라 여러 유형의 부동 소수점을 모두 가져올 수 있다고 말하면 n^2 가능한 조합을 얻게 될 것입니다. –

+0

OP가 모든 유형 X 및 Y 유형을 알고 OP가 명시 적으로 역전을 수행해야하는 경우가 아니면 작동하지 않습니다. (즉, ''과 ''에 대한 명시적인 전문화를 정의해야합니다.) 아마도 OP는'X'와'Y'의 모든 값이 무엇인지 모릅니다. –