Return type autodetection in templates

T

Tim Wesson

Does anyone know if it is possible to choose between the below
templates (or similar ones) according to the promotion rules for
types T and U?

Thanks,

Tim Wesson.

[...]

template<typename T, typename U>
inline matrix<T> operator+(const matrix<T>& m, const matrix<U>& n)
{ return matrix<T> (m) += n; }

template<typename T, typename U>
inline matrix<U> operator+(const matrix<T>& m, const matrix<U>& n)
{ return matrix<U> (m) += n; }

int main (void)
{
matrix<double> matd1, matd2;
matrix<float> matf1, matf2;

cout << matd1 * matf1 << '\n'; // should print matrix<double> ...
cout << matf2 * matd2 << '\n'; // should print matrix<double> ...
}
 
H

Howard Hinnant

| Does anyone know if it is possible to choose between the below
| templates (or similar ones) according to the promotion rules for
| types T and U?
|
| Thanks,
|
| Tim Wesson.
|
| [...]
|
| template<typename T, typename U>
| inline matrix<T> operator+(const matrix<T>& m, const matrix<U>& n)
| { return matrix<T> (m) += n; }
|
| template<typename T, typename U>
| inline matrix<U> operator+(const matrix<T>& m, const matrix<U>& n)
| { return matrix<U> (m) += n; }
|
| int main (void)
| {
| matrix<double> matd1, matd2;
| matrix<float> matf1, matf2;
|
| cout << matd1 * matf1 << '\n'; // should print matrix<double> ...
| cout << matf2 * matd2 << '\n'; // should print matrix<double> ...
| }

You can sort of do this today. But it doesn't scale well if you have
lots of different types to combine. For just float and double you
might try something like:

template <class T, class U> struct promote;
template <> struct promote<double, double> {typedef double type;};
template <> struct promote<double, float> {typedef double type;};
template <> struct promote<float, double> {typedef double type;};
template <> struct promote<float, float> {typedef float type;};

template<typename T, typename U>
inline
matrix<typename promote<T,U>::type>
operator+(const matrix<T>& m, const matrix<U>& n)
{
matrix<typename promote<T,U>::type> temp(m);
temp += n;
return temp;
}

This also shows a potential optimization: Assuming matrix::eek:perator+=
returns a matrix&, don't return that. Instead return the temp directly
as shown above. The former disables return value optimization. The
latter does not.

If you happen to be running on gnu, or Metrowerks CodeWarrior, you
might try __typeof__:

template<typename T, typename U>
inline
matrix<__typeof__(T() + U())>
operator+(const matrix<T>& m, const matrix<U>& n)
{
matrix<__typeof__(T() + U())> temp(m);
temp += n;
return temp;
}

This scales better, but isn't standard. However the committee is hotly
debating a typeof-like animal for C++0X.
 
T

Tim Wesson

Howard Hinnant said:
| Does anyone know if it is possible to choose between the below
| templates (or similar ones) according to the promotion rules for
| types T and U?
|
| Thanks,
|
| Tim Wesson.
|
| [...]
|
| template<typename T, typename U>
| inline matrix<T> operator+(const matrix<T>& m, const matrix<U>& n)
| { return matrix<T> (m) += n; }
|
| template<typename T, typename U>
| inline matrix<U> operator+(const matrix<T>& m, const matrix<U>& n)
| { return matrix<U> (m) += n; }
|
| int main (void)
| {
| matrix<double> matd1, matd2;
| matrix<float> matf1, matf2;
|
| cout << matd1 * matf1 << '\n'; // should print matrix<double> ...
| cout << matf2 * matd2 << '\n'; // should print matrix<double> ...
| }

You can sort of do this today. But it doesn't scale well if you have
lots of different types to combine. For just float and double you
might try something like:

template <class T, class U> struct promote;
template <> struct promote<double, double> {typedef double type;};
template <> struct promote<double, float> {typedef double type;};
template <> struct promote<float, double> {typedef double type;};
template <> struct promote<float, float> {typedef float type;};

template<typename T, typename U>
inline
matrix<typename promote<T,U>::type>
operator+(const matrix<T>& m, const matrix<U>& n)
{
matrix<typename promote<T,U>::type> temp(m);
temp += n;
return temp;
}

This also shows a potential optimization: Assuming matrix::eek:perator+=
returns a matrix&, don't return that. Instead return the temp directly
as shown above. The former disables return value optimization. The
latter does not.

If you happen to be running on gnu, or Metrowerks CodeWarrior, you
might try __typeof__:

template<typename T, typename U>
inline
matrix<__typeof__(T() + U())>
operator+(const matrix<T>& m, const matrix<U>& n)
{
matrix<__typeof__(T() + U())> temp(m);
temp += n;
return temp;
}

This scales better, but isn't standard. However the committee is hotly
debating a typeof-like animal for C++0X.

Thankyou, this is as good an answer as I could hope for. I'm just getting
to grips with C++, hence the attempt to write a generic matrix program.
 
T

Tim Wesson

[...]
If you happen to be running on gnu, or Metrowerks CodeWarrior, you
might try __typeof__:

template<typename T, typename U>
inline
matrix<__typeof__(T() + U())>
operator+(const matrix<T>& m, const matrix<U>& n)
{
matrix<__typeof__(T() + U())> temp(m);
temp += n;
return temp;
}

This scales better, but isn't standard. However the committee is hotly
debating a typeof-like animal for C++0X.

Thankyou, this is as good an answer as I could hope for. I'm just getting
to grips with C++, hence the attempt to write a generic matrix program.

Sadly this doesn't work using g++. Still, nice to know it's in the
pipeline!

http://gcc.gnu.org/PR11578

Cheers,

Tim Wesson
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top