2

I have a class MyType that implements a user-defined arithmetic type. This class provides the following conversion operator

struct MyType 
{ ...
  operator double()
  { 
    return to_double(); // This converts my type to a double value
  }
... };

Using this class as follows works fine:

double d = MyType(1);

However, using this class as type within std::complex, e.g.

#include <complex>
std::complex<double> c = std::complex<MyType>(1,1);

fails with the following compiler error:

error: conversion from 'std::complex<MyType>' to non-scalar type 'std::complex<double>' requested

Any help to solve this problem is appreciated.

Matthias

Stefan Scheller
  • 953
  • 1
  • 12
  • 22

2 Answers2

3

The specializations std::complex<float>, std::complex<double>, and std::complex<long double> are LiteralTypes for representing and manipulating complex numbers.

The effect of instantiating the template complex for any other type is unspecified.

So std::complex<MyType> is "problematic"...

Ignoring that part,

whereas std::complex<T> has generic converting constructor, specialization std::complex<double> only provide conversions from other floating complex versions.

But operator= allows generic conversion for all versions (Only Msvc accepts the code though).

You have to provide your own (explicit/named) conversion function:

std::complex<double> to_complex_double(std::complex<MyType>& c)
{
#if 0
     std::complex<double> res;
     res = c; // gcc/clang doesn't accept that.
     return res;
#else
     return {c.real(), c.imag()};
#endif
}
Community
  • 1
  • 1
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I re-read doc, and `std::complex` is mostly unspecified... – Jarod42 Apr 29 '20 at 12:09
  • I can implement a `to_complex_double` conversion function but that does not solve my problem, I guess. I want to use this inside the Eigen library which, internally, makes use of `return static_cast(x);`, whereby `x` is `const std::complex&` and `NewType` is `std::complex`. Is it possible to make this work? – Matthias Möller Apr 29 '20 at 12:39
  • Even if `std::complex` was not unspecified, the primary template doesn't allow that. specialize `std::complex` would allow to have expected behavior (unsure if it is allowed to specialize `std::complex` though) – Jarod42 Apr 29 '20 at 12:45
  • And from [what-can-and-cant-i-specialize-in-the-std-namespace](https://stackoverflow.com/questions/8513417/what-can-and-cant-i-specialize-in-the-std-namespace/8513497#8513497), `std::complex` cannot be specialized. – Jarod42 Apr 29 '20 at 12:51
0

Does this (not particularly elegant) workaround help?

std::complex<MyType> dummy(1,1);
std::complex<double> c1(
    static_cast<double>(dummy.real()), static_cast<double>(dummy.imag()));

I tried all kinds of different constructors and assignment operators of std::complex but did not find a more "implicit" way of converting.

I think this is related: Why doesn't a conversion function work with std::string?

Stefan Scheller
  • 953
  • 1
  • 12
  • 22