Info:tipo devuelto de función de plantilla
Actualmente estoy tratando de aprender metaprogramming plantilla (siguiendo this book). Un ejemplo útil que dan es para el análisis dimensional. Lo implementé como en el libro y todo estuvo bien; see here.
Mi problema, sin embargo, es que quiero utilizar el marco de análisis dimensional con tipos mixtos. Con esto quiero decir que podrías haber dicho un escalar con dimensiones de masa multiplicando un vector con dimensiones de aceleración para dar una fuerza vectorial. Tal como está en el enlace, solo funcionan con el mismo tipo T
para la entrada y la salida de todas las operaciones.
tengo una clase 3-vector que tiene todas las operaciones necesarias para la multiplicación con/dividiendo por escalares, etc por lo que me gustaría hacer algo como
quantity<double,mass> m(1.0);
quantity<vect,acceleration> a(vect(0.0,0.0,-9.81));
quantity<vect,force> f = m*a;
Primer intento:
Para lograr esto traté de ejemplificar los ejemplos del libro para manejar dos tipos diferentes como entradas a operator*
y operator/
, sin embargo, choqué contra una pared cuando se trata del tipo de devolución.
Yo sé que aquí el tipo de retorno de double * vect
es vect
pero si son al revés vect * double
sigue siendo un vect
. Peor; en principio, el tipo de devolución podría ser cualquier cosa. Así que quiero una manera de extender la operator*
a algo así como
template<class T1, class T2, class Dim1, class Dim2>
quantity<X, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2)
{
return quantity<X,
typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
(q1.value()*q2.value());
}
donde X
es el tipo de retorno de q1.value()*q2.value()
y se deduce en tiempo de compilación. Intenté simplemente agregar otra clase de plantilla T3
a la firma y hacer que devuelva T3
, pero parece que no puede deducir qué debería ser T3
.
Segundo intento:
siguiente que trató de usar decltype
de la siguiente manera
template<class T1, class T2>
struct return_type
{
auto mult_f(const T1& a, const T2& b)->decltype(a*b){return a*b;}
typedef decltype(mult_f) type;
};
template<class T1, class T2, class Dim1, class Dim2>
quantity<typename return_type<T1,T2>::type, typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
operator*(const quantity<T1,Dim1>& q1, const quantity<T2,Dim2>& q2)
{
return quantity<typename return_type<T1,T2>::type,
typename boost::mpl::transform<Dim1,Dim2,boost::mpl::plus<_1,_2> >::type>
(q1.value()*q2.value());
}
Sin embargo, esto arroja una multitud de errores de compilación incomprensibles.
Pregunta:
Mi pregunta es, entonces, estoy usando decltype
de la manera correcta pero falta alguna sintaxis, por ejemplo, un especificador typename
en alguna parte? O; ¿Es posible hacerlo de esta manera y si no es posible calcular el tipo de retorno de una función?
Gracias.
Sí, podía decir por la salida del compilador que obtenía la firma de la función completa. No sé por qué estaba complicando tanto las cosas, tu ejemplo compila bien :) El requisito de constructor predeterminado no es un problema para mí aquí. – Dan
@Dan: tenga en cuenta que el libro se escribió antes de la disponibilidad de C++ 11 y 'decltype' /' auto', lo que hizo que las cosas ** mucho ** fueran más complicadas. –
Reemplace 'decltype (T1() * T2())' con 'decltype (std :: declval() * std :: declval ())' y ya no necesita construcciones predeterminadas. –
ildjarn