C ++ returns more accurate information about two template arguments from a function?

I am wondering if there is a way to do this in C ++. Say I have a template vector class:

template <typename T> class vector { public: vector(T a, T b, T c) : x(a), y(b), z(c) {} T x,y,z; }; 

And then I have a templated addition operator:

 template <typename A, typename B> vector<A> operator +(const vector<A> &a, const vector<B> &b) { return vector<A>(a.x+bx, a.y+by, a.z+bz); } 

I am curious if this operator can be modified so that the result depends on which of the two types A and B is more accurate, except that it manually specializes in it.

For example:

 vector<float> + vector<double> would produce a vector<double>, vector<long double> + vector<float> would produce a vector<long double> 

I assume that in C ++ there is no automatic support, but I thought I would ask.

+6
c ++ templates
source share
9 answers

There is no built-in support in the form of a library, but you can execute it using a conditional ( ?: Statement.

In response to another answer, Johannes Schaub posted a promote<T, U> template that complements the logic pretty well. With the template you can write:

 template <typename A, typename B> vector< typename promote<A, B>::type > operator+(const vector<A> &a, const vector<B> &b) { return vector< typename promote<A, B>::type >(a.x+bx, a.y+by, a.z+bz); } 
+9
source share

in C ++ 0x, you can say:

 template <typename A, typename B> auto operator +(const vector<A> &a, const vector<B> &b) -> vector<decltype(ax + bx)> { //... } 

In C ++ 03, you need to define all the combinations yourself, although you can do this in the op_traits reuse op_traits , which can be applied to various different operators. James McNellis gives some details about this in his answer

+7
source share

Andrei Alexandrescu discussed this in his DDJ article April 1, 2001 Generic: Min and Max Redivivus .

In short, the general problem is very complex.

Andrew used 80 lines of support code, these lines, in turn, relied on the Loki library.

Greetings and hth ,.

+3
source share

There is a relatively easy way to do this with specialized templates.

  template< typename A > struct TypePrecision { static const int precisionLevel; }; template< typename A > const int TypePrecision< A >::precisionLevel = 0; template<> struct TypePrecision< float > { static const int precisionLevel; }; template<> struct TypePrecision< long float > { static const int precisionLevel; }; template<> struct TypePrecision< double > { static const int precisionLevel; }; template<> struct TypePrecision< long double > { static const int precisionLevel; }; template<> const int TypePrecision< float >::precisionLevel = 1; template<> const int TypePrecision< long float >::precisionLevel = 2; template<> const int TypePrecision< double >::precisionLevel = 3; template<> const int TypePrecision< long double >::precisionLevel = 4; 

Then you use this to create a higher level of accuracy.

  template < typename A , typename B > struct HigherPrecisionType { static const int APrecision; static const int BPrecision; }; template < typename A , typename B > const int HigherPrecisionType< A, B >::APrecision= TypePrecision< A >::precisionLevel; template < typename A , typename B > const int HigherPrecisionType< A, B >::BPrecision= TypePrecision< B >::precisionLevel; 

I'm not sure how to compare them to get a typedef in the specialization for the appropriate type. But I hope you get the idea

+1
source share

The Type Selection template may be useful here (read about it in Modern C ++ Design).

 template <bool flag, typename T, typename U> struct Select { typedef T Result; }; template <typename T, typename U> struct Select<false, T, U> { typedef U Result; }; ... template <typename A, typename B> vector<Select<sizeof(A) > sizeof(B), A, B>::Result> operator +(const vector<A> &a, const vector<B> &b) { return vector<Select<sizeof(A) > sizeof(B), A, B>::Result>(a.x+bx, a.y+by, a.z+bz); } 
+1
source share

I choose a larger type:

Helper Templates:

 template<bool b, typename A, typename B> struct choose_if { typedef A type; }; template<typename A, typename B> struct choose_if<false, A, B> { typedef B type; }; template<typename A, typename B> struct greater { static const bool value = sizeof(A) > sizeof(B); typedef vector<typename choose_if<value, A, B>::type> type; }; 

Now use it:

 template <typename A, typename B> typename greater<A, B>::type operator +(const vector<A> &a, const vector<B> &b) { typedef typename greater<A, B>::type type; return type(a.x+bx, a.y+by, a.z+bz); } 

Watch the online demo: http://www.ideone.com/PGyA8

+1
source share

You can complete your task using the overload function. This means that in addition to the generic:

 template <typename A, typename B> vector<A> operator +(const vector<A> &a, const vector<B> &b) { return vector<A>(a.x+bx, a.y+by, a.z+bz); } 

you also declare overloads for certain types, and then they are then used, and not mainly:

 vector<double> operator +(const vector<float> &a, const vector<double> &b) { return vector<double>(a.x+bx, a.y+by, a.z+bz); } 

Another option would be to implement conversion operators in a vector template for the required types. Let the float vector be able to return a double vector through the operator.

0
source share

Yeah. Here's the C ++ 03 method:

 template < typename T1, typename T2 > struct which_return; template < typename T > struct which_return<T,T> { typedef std::vector<T> type; }; template < > struct which_return<int,double> { typedef std::vector<double> type; }; template < > struct which_return<double,int> : which_return<int,double> {}; // etc... template < typename T1, typename T2 > typename which_return<T1,T2>::type operator+ (std::vector<T1> const&, std::vector<T2> const&) { // ... } 

Obviously, you are doing this with C ++ 0x if you can.

0
source share

You can never do this:

vector<float> + vector<double> would produce a vector<double>

without massive cheating or returning a pointer to some kind of gizmo of your own design, because operator+ should return the type that is known at compile time. You are asking to return the type defined at runtime.

-one
source share

All Articles