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++ шаблон автоматического продвижения по типу

Например, если a является int и Ь int затем вернуть Foo<int>, если один или оба из них являются double затем возвращаются Foo<double>.

Это можно сделать?

+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 +' без типа [-fpermissive]' Является ли 'auto' особенностью C++ 11? –

+0

@Tran: Я подтвердил, что это действительно так: возвращаемый конец необходим только для сценариев типа decltype. Это должно делать то, что вы хотите. –

+0

@Tran: добавлен пример IDEOne, работающий с вашим классом образцов. –

4

(C++ 11): Используйте выражение declval внутри dectype:

#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 предоставлял явные специализации для обратных. (То есть нужно определить явную специализацию для '' и '') Предположительно, ОП не знает, что все значения 'X' и' Y'. –

Смежные вопросы