Return function type of template

Information:

I am currently trying to learn about metaprogramming patterns (following this book ). One useful example they give is size analysis. I implemented it, as in a book, and everything was in order; see here .

My problem, however, I want to use a mixed-size dimension analysis framework. By this I mean that you could say a scalar with mass sizes multiplying a vector with acceleration sizes to give a vector force. Since it is in the link, they only work with the same type T for input and output of all operations.

I have a 3-vector class that has all the necessary operations for multiplying by / division by scalars, etc., so I would like to do something like

 quantity<double,mass> m(1.0); quantity<vect,acceleration> a(vect(0.0,0.0,-9.81)); quantity<vect,force> f = m*a; 

First try:

To achieve this, I tried to extract examples from the book to handle two different types as contributions to operator* and operator/ , however I hit the wall when it comes to the return type.

Here I know that the return type double * vect is equal to vect , but if they are in the opposite direction vect * double , it is still vect . Worse; in principle, the return type can be any. So I want to extend operator* to something like

 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()); } 

where X is the return type q1.value()*q2.value() and is output at compile time. I tried just adding another T3 template class to the signature and returning it to T3 , but it doesn't seem to be able to determine what T3 should be.

Second attempt:

Next, I tried to use decltype as follows

 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()); } 

However, this gives rise to many obscure compiler errors.

Question:

My question is whether I am using decltype , but some syntax is missing, for example. a typename specifier somewhere? Or; is it possible to do so, and if not, how can we calculate the return type of the function?

Thanks.

+6
source share
1 answer

So, first, the type return_type<T1,T2>::type is not what you expect, but the type of method, namely T3 (return_type::*)(const T1&, const T2&) with T3 - the type you expect . If you want to use an intermediate class, you can use:

 template <typename T1, typename T2> struct return_type { typedef decltype(std::declval<T1>()*std::declval<T2>()) type; }; 

But you can also directly use decltype(T1()*T2()) to get the product type.

Change I edited the code with the ildjarn clause, so there is no need for default construct types. Remember to enable <utility>

+6
source

Source: https://habr.com/ru/post/918454/


All Articles