2010-09-30 10 views
8

¿Es posible algo así?Deduce el tipo de retorno de operador/función para plantillas

// We can even assume T and U are native C++ types 
template<typename T, typename U> 
magically_deduce_return_type_of(T * U) my_mul() { return T * U; } 

¿O alguien tendría que hackear una estructura return_type y especializarla para cada par de tipos nativos?

Respuesta

12

Oído de decltype?

En C++0x que puede hacer

template<class T, class U> 
auto mul(T x, U y) -> decltype(x*y) 
{ 
    return x*y; 
} 
+0

¿Es posible algo así sin C++ 0x? – Chris

+1

@Chris: ¡Nopes! Esta función está disponible en MSVC++ [2010] y en g ++ (versión 4.3 y superior). –

+0

no, esa es una de las razones por las que se han agregado elementos "automáticos" y "decltype" para solucionar este inconveniente que causaba problemas en áreas como programación genérica y tener que adivinar tipos complejos como iteradores de contenedor, etc. El operador no estándar "typeof" existía en algunos compiladores para soportar esto, pero ahora ha sido estandarizado para nuestro placer. – David

0

pre-C++ 0x

no saben exactamente lo que quiere lograr, por lo que:

template<typename T, typename U> 
void my_mul(T t, U u, bool& overflow) 
{ 
    my_mul_impl(t*u, overflow); 
} 

template<typename TmultU> 
void my_mul_impl(TmultU mult, bool& overflow) 
{ 
    //here you know the type and can do something meta-weird :) 
    if(mult > type_traits<TmultU>::max_allowed_in_my_cool_program()) 
     overflow = true; 
} 

Hay more

2

Uso Visual Studio 2008, así que tuve que crear una forma que no sea C++ 0x. Terminé haciendo algo como esto.

template<typename T> struct type_precedence { static const int value = -1; }; 
template< > struct type_precedence<long double> { static const int value = 0; }; 
template< > struct type_precedence<double> { static const int value = 1; }; 
template< > struct type_precedence<float> { static const int value = 2; }; 
template< > struct type_precedence<unsigned long long> { static const int value = 3; }; 
template< > struct type_precedence<long long> { static const int value = 4; }; 
template< > struct type_precedence<unsigned long> { static const int value = 5; }; 
template< > struct type_precedence<long> { static const int value = 6; }; 
template< > struct type_precedence<unsigned int> { static const int value = 7; }; 
template< > struct type_precedence<int> { static const int value = 8; }; 
template< > struct type_precedence<unsigned short> { static const int value = 9; }; 
template< > struct type_precedence<short> { static const int value = 10; }; 
template< > struct type_precedence<unsigned char> { static const int value = 11; }; 
template< > struct type_precedence<char> { static const int value = 12; }; 
template< > struct type_precedence<bool> { static const int value = 13; }; 

///////////////////////////////////////////////////////////////////////////////////////// 

template<typename T, typename U, bool t_precedent = ((type_precedence<T>::value) <= (type_precedence<U>::value))> 
struct precedent_type { 
    typedef T t; 
}; 
template<typename T, typename U> 
struct precedent_type<T,U,false> { 
    typedef U t; 
}; 

///////////////////////////////////////////////////////////////////////////////////////// 

template<typename T, typename U> 
typename precedent_type<T,U>::t my_mul() { return T * U; } 

EDITAR: Este es el ejemplo: de hecho, estoy haciendo esto para multiplicar vectores. Se ve algo como esto:

template<int N, typename T, typename U> 
vec<N,typename precedent_type<T,U>::t> operator *(const vec<N,T>& v1,const vec<N,U>& v2) { 
    ... 
} 

... 

double3 = float3 * double3; 
float4 = float4 * int4; 
etc. 
+0

podría dar un ejemplo de cómo usaría my_mul()? – Alsk

+0

puede dejar que el compilador deduzca el tipo de resultado que pasa una variable para almacenar el resultado por referencia a la función: 'mult (result_double3, float3, double3)'. Sintaxis no conveniente, pero ahorraría tiempo en hackeo manual. – Alsk

8

Usted puede hacer esto de no C++0x código:

template<typename T, typename U> class Mul 
{ 
    T t_; 
    U u_; 
public: 
    Mul(const T& t, const U& u): t_(t), u_(u) {} 
    template <class R> 
    operator R() 
    { 
    return t_ * u_; 
    } 
}; 

template<typename T, typename U> 
Mul<T, U> mul(const T& t, const U& u) 
{ 
    return Mul<T, U>(t, u); 
} 

Uso: carbón t = 3; corto u = 4; int r = mul (t, u);

Aquí tenemos dos tipos de deducciones. Declaramos implícitamente el tipo de devolución por uso, no exactamente decltype (T * U)

Cuestiones relacionadas