2

I overloaded the *= operator with this member function:

template<class U>
Matriz<T> & operator*=(const Matriz<U> & valor);

And also I have a constructor to matriz like this:

Matriz(const std::vector<T> & vector);

Well, I would like to make something like this:

double vetor[3] = { 1, 2, 3 };
std::vector<double> vec(vetor, vetor + 3);
Matriz<double> A("src//imatriz.dat"); //Creates a matrix with parameters from a file.
A*=vec;

That is, I would like to multiply a matrix by a vector. The problem is that compiler returns that there is no match for the operator.

---EDIT2---

As suggested, I also tried this:

template<class U>
friend Matriz<T> & operator*=(Matriz<U> & lhs, const Matriz<U> & rhs)

but A*=vec still doesn't work.

Any idea? If you need more code there's no problem to put it here.

djf
  • 6,592
  • 6
  • 44
  • 62
Leandro Lima
  • 1,140
  • 3
  • 24
  • 42
  • If your overload is a global function (can't understand from your paste), it will fail. You may consider making it a class method. – diegoperini May 27 '13 at 04:29
  • It is a class method. – Leandro Lima May 27 '13 at 04:30
  • then you should overload `*=` taking vector as a parameter?`A*=vec;` should embed a call to something like this `operator*=(A,vec);` where vec is of type vector. – Koushik Shetty May 27 '13 at 04:33
  • Instantiation of variable A seems weird. Try something like this: `Matriz A = Matriz(vec)` – diegoperini May 27 '13 at 04:33
  • 1
    @Leandro The answers so far are all correct, but your underlying question **why exactly the compiler didn't perform an implicit conversion** hasn't been addressed. The thread [C++ implicit type conversion with template](http://stackoverflow.com/questions/9787593/c-implicit-type-conversion-with-template) answers it. – djf May 27 '13 at 07:27
  • @djf I have tried this answer, like you can see in my new EDIT2, but it doesn't work. – Leandro Lima May 27 '13 at 12:47
  • @Leandro My comment wasn't meant as a critique or anything. I just wanted to point out that the behavior you're getting is correct according the C++ standard – djf May 27 '13 at 12:56
  • @djf Yeah, I can see that it isn't a critique, no problem! I want just to find out a way to solve this problem. That answer that you posted is pointing to a correct way but something else is wrong into my code...thanks for your comment, it was the best try until now. – Leandro Lima May 27 '13 at 13:00
  • @Leandro @billz and @Koushik both gave solutions which work. Let me reiterate the problem quickly. When you're working with templates, the compiler first tries to figure out the correct values of U and T (your template parameters). It doesn't even look at implicit conversions, default arguments, overloads etc. The reason it fails to compile is because there's simply no substitution for U to turn the expression `Matriz & operator*=(const Matriz & valor)` into `Matriz & operator*=(const std::vector& valor)`. It has to give up at this point. I hope this isn't too convoluted. – djf May 27 '13 at 14:48
  • So @djf is there no way to do it without implement another operator only to take care of vectors? – Leandro Lima May 27 '13 at 15:47
  • @Leandro In _general_ no. There are some pretty advanced techniques.... Anyway, defining another overload for vectors seems to be your best option – djf May 27 '13 at 20:23

3 Answers3

2

To make below statement work:

A *= vec;

You need another operator*= for vector type:

template<class U>
Matriz<U> & operator*=(const std::vector<U> & valor);

constructor will operate on new constructed object but will not convert existing object, for example, below statement should work:

A*=std::vector<double>(vetor, vetor + 3);

see live sample

billz
  • 44,644
  • 9
  • 83
  • 100
  • But if I pass a vector to the operator with matrix, why not it converts to matrix? See, there is a constructor that receives a vector. – Leandro Lima May 27 '13 at 04:42
  • +1 thats exactly what i also said. or may be he can take another template parameter which tells the type that should be multiplied with. – Koushik Shetty May 27 '13 at 04:43
  • @Leandro you are multiplying and not constructing anything there. there is no default conversion as you expect. – Koushik Shetty May 27 '13 at 04:45
  • This solution I have also tried. It's ok, works well, but I wanna know why I can't make it without this overloading of the operator. – Leandro Lima May 27 '13 at 04:45
  • Yeah, but, if I pass a int to get multiplied by a double it works fine...I would like to do something like this. – Leandro Lima May 27 '13 at 04:47
  • Yeah, exactly, but I put this in my code and it doesn't work. – Leandro Lima May 27 '13 at 05:00
  • Hey @billz I made some changes in your code and tried it. It seems that maybe the problem is with template... – Leandro Lima May 27 '13 at 05:19
  • quite possible, coz the implicit conversion from vector to Matriz is obvious as you have a constructor which takes vector as parameter. – billz May 27 '13 at 05:20
  • You need to post more code, also post what's the error message. ;) – billz May 27 '13 at 05:33
  • In the question comments, @djf gave me an idea about what I need, but it still doesn't wokr. So, See there the problem. If you still need more code I could try to give you some. – Leandro Lima May 27 '13 at 12:55
1

you could maybe do this

template<typename T, typename conv =  std::vector<T> > //for the Matriz class

now operator is

Matriz<T>& operator *= (const conv& vec); 

also the constructor as below

Matriz(const conv& vec);

EDIT 2:
you could do this otherwise

for the constructor use this

template<typename TYPE2MUL>
Matriz(const TYPE2MUL& var)

after this you can use

A *= vec; 

because it will call op as so operator *=(A,Matriz<vector>(vec)); no need for EDIT 1 or prior to that.

Koushik Shetty
  • 2,146
  • 4
  • 20
  • 31
0

If you don't want to define another operator '=', the following code is OK.

A *= Matriz<double>(vec).
mumu
  • 197
  • 7