I have inherited some C++ code that needs to average some complex numbers. Given a collection, it adds those values which pass a condition to an accumulator, then divides by the number of values added.
Using gcc (currently, gcc 8) I get template argument deduction/substitution failed
if I use stand-alone operator/
but it works fine with std::complex::operator/=
. Such a nuance seems fragile for follow-on maintainers.
So what is the proper way to get an average of complex numbers?
And is it reasonable that the language only partially supports division of complex numbers by integral types?
std::complex<double> A[32] = { /* initialization left to the reader */ };
int count = 0;
std::complex<double> sum;
for (auto i = 0; i < 32; ++i) {
if ( i % 2 ) { // arbitrary condition, not important
sum += A[i];
++count;
}
}
auto avg = sum / count; // this is ambiguous
sum /= count; // this is not
(representative error, for the curious)
main.cpp: In function ‘int main()’:
main.cpp:16:16: error: no match for ‘operator/’ (operand types are ‘std::complex<double>’ and ‘int’)
auto avg = sum / count; // this is ambiguous
~~~~^~~~~~~
In file included from main.cpp:2:0:
/usr/include/c++/7/complex:434:5: note: candidate: template<class _Tp> std::complex<_Tp> std::operator/(const _Tp&, const std::complex<_Tp>&)
operator/(const _Tp& __x, const complex<_Tp>& __y)
^~~~~~~~
/usr/include/c++/7/complex:434:5: note: template argument deduction/substitution failed:
main.cpp:16:18: note: mismatched types ‘const std::complex<_Tp>’ and ‘int’
auto avg = sum / count; // this is ambiguous
^~~~~
In file included from main.cpp:2:0:
/usr/include/c++/7/complex:425:5: note: candidate: template<class _Tp> std::complex<_Tp> std::operator/(const std::complex<_Tp>&, const _Tp&)
operator/(const complex<_Tp>& __x, const _Tp& __y)
^~~~~~~~
/usr/include/c++/7/complex:425:5: note: template argument deduction/substitution failed:
main.cpp:16:18: note: deduced conflicting types for parameter ‘const _Tp’ (‘double’ and ‘int’)
auto avg = sum / count; // this is ambiguous
^~~~~
In file included from main.cpp:2:0:
/usr/include/c++/7/complex:416:5: note: candidate: template<class _Tp> std::complex<_Tp> std::operator/(const std::complex<_Tp>&, const std::complex<_Tp>&)
operator/(const complex<_Tp>& __x, const complex<_Tp>& __y)
^~~~~~~~
/usr/include/c++/7/complex:416:5: note: template argument deduction/substitution failed:
main.cpp:16:18: note: mismatched types ‘const std::complex<_Tp>’ and ‘int’
auto avg = sum / count; // this is ambiguous
^~~~~
Not sure what the most proper way to do division for it, but if you look through all the parameters operator/
and operator/=
take, you would notice that:
operator/
takes in either std::complex<T>
or T
.
double
, then it should only take in another value that is either double
or complex<double>
.clang
straight up gave invalid operands to binary expression ('std::complex<double>' and 'int')
erroroperator/=
takes in std::complex<T>
or T
, while also have specialization for float
, double
, and long double
.
operator/=
would have a change to be implicit converted to float
, double
, or long double
, which int
can do.