Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   template function with automatically templatized return type. (http://www.velocityreviews.com/forums/t668026-template-function-with-automatically-templatized-return-type.html)

Daniel Pitts 01-30-2009 06:55 PM

template function with automatically templatized return type.
 
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,
scalar_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?

Thanks,
Daniel.
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Noah Roberts 01-30-2009 08:56 PM

Re: template function with automatically templatized return type.
 
Daniel Pitts wrote:

> 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,
> scalar_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.


How could it?

>
> Is there any way to do this?


No.

Noah Roberts 01-30-2009 09:01 PM

Re: template function with automatically templatized return type.
 
Daniel Pitts 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();


Actually, there probably is a way to do this but it's going to be some
sort of magic that I don't know. Clearly not what you've started with.
You need to somehow retrieve the OtherType type from metafunction
programming so that you can tell the operator * for vector * type what
to return.

So, get learning MPL and dig through the boost::type_traits library that
will be part of the next standard.

One easy method, but one that doesn't scale well, would be to create a
trait for "sometype" that is like "multiplication_type<X>" that returns
OtherType for SomeType.

Vidar Hasfjord 01-31-2009 10:09 PM

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,
> * * * * * * * * * * * * * * * * * * scalar_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


All times are GMT. The time now is 12:50 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.