1

Consider the following code

#include <complex>
#include <iostream>

int main(int argc, char **argv)
{
    std::complex<double> a = 1+1i;
    std::cout<<"a ="<<a<<"\n";
    return 0;
}

When I compile using Apple LLVM version 8.0.0 (clang-800.0.42.1) and the output that I get is

a =(1,0)

Can someone explain why the imaginary part is getting initialised with zero?

Ivan Kolesnikov
  • 1,787
  • 1
  • 29
  • 45
Coniferous
  • 111
  • 5
  • Seems to work fine: http://ideone.com/Qa7698 did you forget to recompile at some point? – Matti Virkkunen Nov 24 '16 at 12:05
  • I was using Apple LLVM version 8.0.0 (clang-800.0.42.1). Not g++!. I will edit the post – Coniferous Nov 24 '16 at 12:07
  • 2
    What happens when you add a using declaration `using namespace std::literals::complex_literals;`? – StoryTeller - Unslander Monica Nov 24 '16 at 12:13
  • Repro: http://melpon.org/wandbox/permlink/QBES5VmGeMrfvZoT Probably some incompatibility between GCC extensions and C++ complex literals. I'd guess the GCC-extension is convertible to a double (the real part), so the `1+1i` is converted to double, then that result is used to initialize the std::complex. – dyp Nov 24 '16 at 12:58
  • See also: http://stackoverflow.com/q/28624861/ – dyp Nov 24 '16 at 13:08

1 Answers1

2

The 1 + 1i is using a (GCC) extension which creates types similar/equivalent to C99's _Complex int type. That type is convertible to a real type like int or double. std::complex is not compatible to _Complex, it does not have any constructors to create a std::complex from a _Complex (*). But std::complex<T> does have a constructor that takes a T. This triggers the aforementioned conversion _Complex -> T -> std::complex<T>.

So the code in the OP is equivalent to:

#include <complex>
#include <iostream>

int main()
{
    double d = 1+1i;
    std::complex<double> a = d;
    std::cout<<"a ="<<a<<"\n";
    return 0;
}

The imaginary part of 1 + 1i is dropped in the conversion to double.


To prevent such surprises, try to compile with warnings and -pedantic. This example seems to be one of the few places where clang actually adds an additional warning with the -pedantic flag (for gcc, -pedantic changes the warning output in many contexts):

prog.cc:6:19: warning: imaginary constants are a GNU extension [-Wgnu-imaginary-constant]
    double d = 1+1i;

(*) IIRC, std::complex was introduced in C++98, while _Complex was introduced in C99.

dyp
  • 38,334
  • 13
  • 112
  • 177
  • 1
    GCC could add `std::complex::complex(_Complex)` for interoperability. This would be fairly safe as it does not appear to add new conversion sequences between C++ types. – MSalters Jun 17 '19 at 11:38