Re: template function with automatically templatized return type.
On Jan 30, 6:55 pm, Daniel Pitts
<newsgroup.spamfil...@virtualinfinity.net> wrote:
I have a Vector (as in math vector) template class.
template <typename component_t>
class Vector { /*...*/ };
It defines what you might expect for operators: =, [] +, -, * (as a
scalar multiply), /, etc...
I have some type which the result of (x*x) is not the same type as x.
OtherType operator*(const SomeType &, const SomeType &).
I would like to be able to define a generic operator* for Vector such
that the following works:
const Vector<OtherType> n = Vector<SomeType>() * SomeType();
I tried
template<typename component_in_t,
typename component_out_t, typename scalar_t>
Vector<component_out_t> operator *(const Vector<component_in_t> &in,
s=
calar_t scalar) {
Vector<component_out_t> result;
for (int i = 0; i < dimensions; ++i) {
result[i] = in[i]*scalar;
}
return result;
}
But my compiler can't infer component_out_t.
Is there any way to do this?
Yes. While C++ doesn't directly support overloading on return type,
you can achieve the effect by returning a proxy that has conversion
operators for the required return types. The conversion operator then
performs the operation. For example:
const int dimensions = 2;
template <typename T>
struct Vector
{
T v_ [dimensions];
T& operator [] (int i) {return v_ [i];}
const T& operator [] (int i) const {return v_ [i];}
};
template <typename T1, typename T2>
struct VectorMultiplication
{
const Vector <T1>* v_;
T2 s_;
VectorMultiplication (const Vector <T1>& v, T2 s)
: v_ (&v), s_ (s) {}
template <typename T3>
operator Vector <T3> () const {
Vector <T3> r = {};
for (int i = 0; i < dimensions; ++i)
r [i] = (*v_) [i] * s_;
return r;
}
};
template <typename T1, typename T2>
VectorMultiplication <T1, T2>
operator * (const Vector <T1>& v, T2 s)
{
return VectorMultiplication <T1, T2> (v, s);
}
// Test
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T>
ostream& operator << (ostream& os, const Vector <T>& v)
{
copy (&v [0], &v [0] + dimensions,
ostream_iterator <T> (os, " "));
return os;
}
void test_overloaded_return_type ()
{
Vector <short> v = {1, 2};
cout << v << endl; // 1 2
Vector <int> r = v * 2;
cout << r << endl; // 2 4
}
You can extend the proxy to a full expression template to optimize
your vector operations. Look up "expression template" for more
information.
Regards,
Vidar Hasfjord