I have a matrix class like below:
template <size_t M, size_t N, typename T>
class Matrix
{
public:
Matrix<M, N, T> operator +(const Matrix<M, N, T>& B) const;
template <size_t P> Matrix<M,P,T> operator*(const Matrix<N, P, T>& B) const;
template <typename T2> operator T2() const;
private:
T data[M][N];
};
// ... the body is in header file too ...//
The body has written fine, and everything works well.
When I define two Matrices as below:
Matrix < 10, 10, int> m1;
Matrix < 10, 10, float> m2;
m1 + m2; // OK
m1 * m2; // error: no match for 'operator*' in 'm1 * m2'
The first ‘+’ operator works well, because an implicit casting has performed on it.
but for second ‘*’ operator for different value types, an error occurs.
error: no match for ‘operator*’ in ‘m1 * m2’
Any idea ?!
UPDATE:
All code is in header file. I have no problem but for ‘*’ operator.
What you can say about ‘+’ operator? I know everything about template/operators/casting… but this problem is like a bug for my gcc compiler!? I wrote a cast-operator and this operator calls before ‘+’ operator, but i dont know why it dose not perform for ‘*’ operator!
The problem is more or less classic. The overload resolution starts by
building a list of possible functions; in this case, functions named
operator*. To do this, it adds alloperator*functions which are inscope to the list, and it tries to instantiate all function templates by
applying type deduction; if type deduction succeeds, it adds the
instantiation of the template to the list. (A function template is
not a function. An instantiation of the function template is a
function.)
The rules for template type deduction are different than those used in
overload resolution. In particular, only a very small set of
conversions are considered. User defined conversion operators are not
considered. The result is that in
m1 * m2, type deduction foroperator*fails (since it would require a conversion which isn’tconsidered). So no instantiation of the function template is added to
the list, and there is no other
operator*.More generally: you’re
operator T2()wouldn’t allow type deductioneven if it were allowed; there are a infinite number of conversions
which would match
operator*. I suspect, in fact, that you’ve made ittoo general; that you want an
operator Matrix<M, N, T2>(). (Not thatthis will help here, but there are contexts where it might eliminate an
ambiguity.)
You might be able to make it work by defining a:
, then doing the conversion inside the operator*. (I haven’t tried it,
and am not sure, but I think your existing
operator*should beconsidered “more specialized”, and thus be chosen when type
deduction succeeds for both.)
Having said this, I think the way you’re doing it is the wrong approach.
Do you really want the return types of
m1 * m2andm2 * m1to bedifferent. For starters, I’d require the client code to make the
conversion explicit (which is the case in your current code); if you do
want to support the implicit conversions, I think you need to make the
operator*a global, use some sort of simple meta-programming todetermine the correct return type (i.e. given Matrices of
longandunsigned, you might want to have a return type ofunsigned long,since this is what mixed type arithmetic with these types gives
otherwise), convert both sides to the target type, and do the arithmetic
on it. A lot of work for what is probably not a very important or
useful feature. (Just my opinion, of course. If your clients really
want the mixed type arithmetic, and are willing to pay for it…)