andyInCambridge
andyInCambridge

Reputation: 1225

c++ generalized operator templating

I'm doing some numerical simulations where it is nice to overload operations on vectors (similar to valarrays). For example, I can write

template <typename T>
vector<T> operator*(const vector<T>& A, const vector<T>& B){
   //blah blah
}

But what if I want to generalize this template so as to act on two different types of vectors and (potentially) return a third type? I.e. I want to write

template <typename T, template U, template V>
vector<V> operator*(const vector<T>& A, const vector<U>& B){
   //blah blah
}

Now, the above does indeed work if I use the operator in a situation "A*B" where A and B are distinct types and return a another distinct type. However, if A and B are the same type, it does not work. Certainly I could define different templates for each combination (i.e. T only, or T and U only, or T, U, and V) but that seems ugly. Is there a way I can use a single template expression of the T,U, and V variety given above and make it work even if "A", "B", and "A*B" are all the same types (or have only 2 different types?)

Upvotes: 3

Views: 225

Answers (3)

pmr
pmr

Reputation: 59811

As others have pointed out you can use decltype to achieve this. C++0x also provides the template common_type which deduces a type to which all it template arguments can be coerced without any specific arithmetic operation. So it can also be used if no overloaded operators are available for the argument types.

Upvotes: 0

Puppy
Puppy

Reputation: 146940

This can work in C++0x with decltype.

template <typename T, template U> 
vector<decltype(declval<T>() + declval<U>())> 
operator*(const vector<T>& A, const vector<U>& B){
   //blah blah
}

Without using this mechanism- and presuming that T and U do not provide their own mechanism- you can't do something like this. You can only handle the situation where T, U, and the return type are all the same type. You can, however, deal with primitive types- there's a Boost type trait for the result of applying operators like + to various primitive types to find the promoted type.

Upvotes: 0

Armen Tsirunyan
Armen Tsirunyan

Reputation: 133014

Now, the above does indeed work if I use the operator in a situation "A*B" where A and B are distinct and return a different type.

To be honest, this doesn't make sense. Your template shouldn't work at all because V cannot be deduced and it is the third template parameter. If you had written:

template <typename V, template T, template U>
vector<V> operator*(const vector<T>& A, const vector<U>& B){
   //blah blah
}

This would "work" but only if you explicitly specified V, something like

operator*<double>(A, B); //where A is vector<int> and B is vector<float>, for example

Surely you want to return a vector<V> where V is the type of the expression T()*U(). This is possible to do in C++11, but not trivially in C++03( I mean, you could do some type-traiting at best). Here's how it's done in C++11:

template <typename T, template U>
vector<decltype(T()*U())> operator*(const vector<T>& A, const vector<U>& B)  
{
   //blah blah
}

HTH

Upvotes: 1

Related Questions