A function template cannot infer a type if the types T and U are the same

This question is related to the answer I received yesterday. For the next function, I get the error couldn't deduce template parameter 'V' if both T and U are std::complex<double> . If T and U different, the function compiles and works as intended.

 template<class T, class U, class V> auto operator*(const T a, const matrix<U> A) -> decltype(std::declval<T>()*std::declval<U>()) { matrix<V> B(A.size(1),A.size(2)); for(int ii = 0; ii < B.size(1); ii++) { for(int jj = 0; jj < B.size(2); jj++) { B(ii,jj) = a*A(ii,jj); } } return B; } 

Usage is as follows:

 std::complex<double> a1; matrix<std::complex<double> > A1; double a2; matrix<std::complex<double> > A2; /* ... */ matrix<std::complex<double> > B1 = a1*A1; // Compiler error matrix<std::complex<double> > B2 = a2*A2; // Compiles and runs fine. 

I should also mention that I am compiling with included g ++ 4.7.3 and C ++ 11.

EDIT:

The workaround I found should also contain this function template:

 template<class T> matrix<T> operator*(const T a, const matrix<T> A) { matrix<T> B(A.size(1),A.size(2)); for(int ii = 0; ii < B.size(1); ii++) { for(int jj = 0; jj < B.size(2); jj++) { B(ii,jj) = a*A(ii,jj); } } return B; } 

With this add-on, both cases above are compiled and executed correctly.

0
source share
3 answers

I think another operator* overload should happen, because V cannot be output given the declaration:

 template<class T, class U, class V> auto operator*(const T a, const matrix<U> A) -> decltype(std::declval<T>()*std::declval<U>()); 

The only way to call this function is to explicitly specify V , for example, operator*<int, long, long>(...) .


Edit: looking at the signature for operator*(T, matrix<T>) in the second code example, it seems like your first code example should read:

 template<class T, class U> auto operator*(const T a, const matrix<U>& A) -> matrix<decltype(a*A(0,0))> { matrix<decltype(a*A(0,0))> B(A.size(1),A.size(2)); for(int ii = 0; ii < B.size(1); ii++) { for(int jj = 0; jj < B.size(2); jj++) { B(ii,jj) = a*A(ii,jj); } } return B; } 

operator*(T,matrix<T>) not necessary as a special case.

+3
source

I think that if T and U are different, another function is called because the compiler is right, V cannot be inferred, period. Even I cannot deduce what you think this parameter should be. Here is the proof that the second does not compile and does not start either , which means that in this case another function is called. The obvious solution is to simply remove the class V template parameter type and just use the inferred type. Perhaps you need something more like it?

Looking at your code again, the one you say does not match complex * matrix , and the second does not match matrix*matrix . what other operator* defined?


Unrelated, there are three common ways to receive parameters: T , const T& or T&& . There are very few reasons to have a const T parameter type. I believe you are missing & ?
+2
source

The problem is not that T and U same, but type V is noted in the function prototype.

Given that you are using V to declare B, which you are returning, and that you are defining the return type as T () * U (), I am wondering what matrix<V> should be.

I would expect B and the return type to be matrix<decltype(declval<T>()*declval<U>())> , without V (this should not be in the parameter list)

+2
source

Source: https://habr.com/ru/post/1493545/


All Articles