overloading template operator arguments?

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

The comperable operator*() to that shown here works for a non-template
class:

template <typename T>
inline Vector3<T> operator*(const Vector3<T>& v, const T& n)
{
Vector3<T> t(v);
return t *= n;
}

For example let Vector3f be a vector of float values. This works fine:
inline Vector3f operator*(const Vector3f& v, const float& n)
{
Vector3f t(v);
return t *= n;
}

It also works when I overload the template form of the operator*=(). For
example this works for the same template class where the first function
shown above fails:

template <typename T>
inline Vector3<T>& Vector3<T>::eek:perator*=(const T& n)
{
_v[0] *= n;
_v[1] *= n;
_v[2] *= n;
return *this;
}

If I replace the T& n with double& n in the first function, it works.

The error I get when using the first form above is this:
error: no match for 'operator*' in 'v3t0 * 5'

Where I have defined:
Vector3<T> v3t0;

Why?
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
J

John Harrison

Steven T. Hatton said:
The comperable operator*() to that shown here works for a non-template
class:

template <typename T>
inline Vector3<T> operator*(const Vector3<T>& v, const T& n)
{
Vector3<T> t(v);
return t *= n;
}

For example let Vector3f be a vector of float values. This works fine:
inline Vector3f operator*(const Vector3f& v, const float& n)
{
Vector3f t(v);
return t *= n;
}

It also works when I overload the template form of the operator*=(). For
example this works for the same template class where the first function
shown above fails:

template <typename T>
inline Vector3<T>& Vector3<T>::eek:perator*=(const T& n)
{
_v[0] *= n;
_v[1] *= n;
_v[2] *= n;
return *this;
}

If I replace the T& n with double& n in the first function, it works.

The error I get when using the first form above is this:
error: no match for 'operator*' in 'v3t0 * 5'

Where I have defined:
Vector3<T> v3t0;

Why?

I'm a bit confused with all these different operators and cases. Could you
provide a complete non-working code sample?

However one guess would be that you need

v3t0 * 5.0

assuming the v3t0 is of type Vector3<double> because C++ will not deduce the
T is double from the first argument, only from the second, and since you
provided an int, it then looking for Vector3<int> as the first argument.

The rules about when C++ can make deductions about template parameters are
quite complex and I'm not able to look them up right now so my explanation
above might not be completely accurate even if the suggested correction is.

john
 
S

Steven T. Hatton

John said:
I'm a bit confused with all these different operators and cases. Could you
provide a complete non-working code sample?

See below.
However one guess would be that you need

v3t0 * 5.0

Darn close! v3t0 * 5.0f
assuming the v3t0 is of type Vector3<double> because C++ will not deduce
the T is double from the first argument, only from the second, and since
you provided an int, it then looking for Vector3<int> as the first
argument.

That can't be exactly what's happening because it fails with both prefix and
postfix operator*(); I think the answer to my problem is to explicitly cast
the scaler operands to T. I.e., v3t0 * T(5);
The rules about when C++ can make deductions about template parameters are
quite complex and I'm not able to look them up right now so my explanation
above might not be completely accurate even if the suggested correction
is.

john
The code show results in this:
Fri Oct 01 13:20:19:> g++ -o vect main.cc
main.cc: In function `int main()':
main.cc:6: error: no match for 'operator*' in '5 * v0'

If I simply swap the comments show below, the code will compile. Note that T
is float in main();

/*
Vect.hh
*/
#ifndef VECT_HH
#define VECT_HH

#include <vector>
#include <iostream>

namespace{
using std::eek:stream;
using std::vector;
}

template<typename T>
class Vect{
public:
Vect(const T& x,
const T& y,
const T& z)
:_v(3)
{
_v[0]=x;
_v[1]=y;
_v[2]=z;
}

inline Vect<T>& operator*=(const T& n);
std::eek:stream& print(ostream& out) const;

private:
vector<T> _v;
};

template<typename T>
Vect<T>& Vect<T>::eek:perator*=(const T& n)
{
_v[0] *= n;
_v[1] *= n;
_v[2] *= n;
return *this;
}

template<typename T>
//Vect<T> operator*(const double& n, const Vect<T>& v)
Vect<T> operator*(const T& n, const Vect<T>& v)
{
Vect<T> t(v);
return t *= n;
}

template<typename T>
//Vect<T> operator*(const Vect<T>& v, const double& n)
Vect<T> operator*(const Vect<T>& v, const T& n)
{
Vect<T> t(v);
return t *= n;
}

template<typename T>
ostream& Vect<T>::print(ostream& out) const
{
return out
<< "Vect<T> = {"
<< _v[0] << ","
<< _v[1] << ","
<< _v[2] << "}\n";
}

template<typename T>
ostream& operator<<(ostream& out, const Vect<T>& v)
{
return v.print(out);
}

#endif



/*
main.cc
*/
#include <iostream>
#include "Vect.hh"

int main() {
Vect<float> v0(3,4,5);
Vect<float> v1 = 5 * v0;
std::cout
<< "v0 == " << v0
<< "v1 == " << v1;
return 0;
}

--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
V

Victor Bazarov

Steven said:
[...]
template<typename T>
//Vect<T> operator*(const double& n, const Vect<T>& v)
Vect<T> operator*(const T& n, const Vect<T>& v)
{
Vect<T> t(v);
return t *= n;
}

Try

template<class T, class U> Vect<U> operator *(T t, const Vect<U>& v)
{
Vect<U> vv(v);
return vv *= t;
}

V
 
J

John Harrison

Steven T. Hatton said:
See below.


Darn close! v3t0 * 5.0f


That can't be exactly what's happening because it fails with both prefix
and
postfix operator*(); I think the answer to my problem is to explicitly
cast
the scaler operands to T. I.e., v3t0 * T(5);

Yes I got that wrong. Template argument deduction is happening on both
parameters. But in the case of v3t0 * 5 you are giving contradictory
information, the first arg says T is float, the second says it's an int.

The best answer is as Victor says, use two template parameters so the
template argument deduction is independent on both parameters to operator*.

john
 
S

Steven T. Hatton

Victor said:
Steven said:
[...]
template<typename T>
//Vect<T> operator*(const double& n, const Vect<T>& v)
Vect<T> operator*(const T& n, const Vect<T>& v)
{
Vect<T> t(v);
return t *= n;
}

Try

template<class T, class U> Vect<U> operator *(T t, const Vect<U>& v)
{
Vect<U> vv(v);
return vv *= t;
}

V
Thanks! Works like a charm! :)
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top