0

I would like to allow the implicit conversion when summing two complex numbers

std::complex<double> a; std::complex<long double> b;
auto c = a+b;

I tried to implement what was suggested here C++ implicit type conversion with template

I defined a derived class of std::complex and I added the friend function that should allow the implicit conversion. Here is my code:

template <typename T> class Complex : private std::complex<T> {  
friend Complex operator+ (Complex const &lhs, Complex const &rhs) return Complex(); };

int main(){  
Complex<double> C1; Complex<long double> C2;

auto Sum = C1+C2;
return(0); }

I don't understand if the problem is in the inheritance from std::complex or in the friend function. Any help would be highly appreciated, Thanks

EDIT:
Omnifarious code works great when left and right arguments of operator+ are both std::complex. How could I allow also the operation complex + int?
Here is my attempt:

template <typename T, typename U>  
auto operator +(const ::std::complex<T> &a,    std::enable_if_t<std::is_arithmetic<U>::value, U>  &b) 
{
typedef decltype(::std::declval<T>() + ::std::declval<U>()) comcomp_t;
typedef ::std::complex<comcomp_t> result_t;
return ::std::operator +(result_t{a}, result_t{b});
}

But, when I try:

int i=1;
auto sum = C1+i;

it doesn't compile. "couldn't deduce template parameter ‘U’"
Why?

Federico
  • 91
  • 3

1 Answers1

2

Here is probably what you want:

#include <complex>
#include <utility> // declval

template <typename T, typename U>
auto operator +(const ::std::complex<T> &a, ::std::complex<U> &b)
{
    typedef decltype(::std::declval<T>() + ::std::declval<U>()) comcomp_t;
    typedef ::std::complex<comcomp_t> result_t;
    return ::std::operator +(result_t{a}, result_t{b});
}

auto test()
{
    using ::std::complex;
    complex<double> x{0, 0};
    complex<long double> y{0, 0};
    return x+y;
}

This requires C++14 for the 'auto' (aka deduced) return type. For C++11 you'd basically have to repeat the decltype expression inside the operator for the return type.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • I'm sorry I meant to type something else and then I accidentally hit prematurely. But to answer your question, you don't need `std::enable_if`, because the standard `operator+` for `std::complex<>` is more specialized and will therefore take precedence in overload resolution. – oisyn Nov 30 '17 at 22:02
  • So what I meant to say was that you didn't need the `enable_if` because I thought you were using it to see whether the types were implicitely addible, but that part of SFINEA automatically follows out of using `decltype` when declaring the return type. You *do* need to declare the return type, though, so you are correct in your assumption you can't use an auto-deduced type as then you won't be able to make use of SFINEA. – oisyn Nov 30 '17 at 22:15
  • @oisyn - I just figured that out. :-) I have a different solution that allows me to use deduced return types. I still don't understand why it didn't work. My guess is because it tries to expand the template for T = U even though it eventually decides it won't use it. And then it calls itself recursively, which it can't because it doesn't even know the return type yet. Which is really kind of a bizarre result. Anyway, I figured out a way around it that's likely a bad idea. – Omnifarious Nov 30 '17 at 22:21
  • I thought that I had to use inheritance because I thought that the operator+ was implemented as a member function of the complex class but is not. Why the friend function doesn't provide implicit conversion as in the answer I linked? Do I have to repeat the same code with decltype for all the different operators (-,*,/)? – Federico Dec 01 '17 at 16:21
  • @Federico - I don't know why the standards committee made the choices they did. I do know that automatic type promotion is considered a C wart, a loosening of the type system that is convenient but creates a lot of weird cases, especially in C++. Of course, C doesn't hold a candle to Javascript or PHP in this regard. But then again, nobody would dream of suggesting C or C++ for what Javascript does. – Omnifarious Dec 01 '17 at 16:26