Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
363 views
in Technique[技术] by (71.8m points)

c++ - typeid(complex<double>(0.0,1.0)) != typeid(1.0i)

Using gcc 4.9 I found that types generated with type literal for complex numbers are not the same as when created by conventional means, i.e.:

typeid(complex<double>(0.0,1.0)) != typeid(1.0i)
  1. Am I making a mistake here?
  2. Is this a compiler bug or intended standard behavior?
  3. If intended standard behavior: What is the rationale behind?

Adding the missing MCVE

#include <complex>
using std::complex;
using namespace std::literals::complex_literals;

#include <iostream>
using std::cout;
using std::endl;

#include <typeinfo>

int main(int argc, char* argv[]) {
    if (typeid(complex<double>(0.0, 1.0)) == typeid(1.0i))
        cout << "types are same as expected" << endl;
    else
        cout << "types are unexpectedly not the same" << endl;

    cout << 1.0i*1.0i << endl;
    cout << complex<double>(0.0, 1.0)*complex<double>(0.0, 1.0) << endl;
}

Compile instructions:

g++ -std=gnu++14 complex.cpp -o complex.exe

Output:

types are unexpectedly not the same
1
(-1,0)

Interestingly the literal does not even seem to be a proper imaginary number. (I am sure I am overlooking something...)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The behaviour of the program depends on the language standard mode of gcc:

There is a gcc extension for a built-in literal suffix i that produces C99 complex numbers. Those are distinct built-in types like _Complex double, as opposed to the "user-defined" class (template specialization) std::complex<double> used in C++.

In C++14, C++ now has a user-defined literal suffix i for complex numbers. That is, a function complex<double> operator"" i(long double) within the std::literals::complex_literals inline namespace.

Those two literal suffixes are competing:

  • In C++11 mode, only the built-in extension is possible, but it is an extension. Hence, gcc only allows it in -std=gnu++11 mode and even warns you about it. Strangely enough, clang allows it even in -std=c++11 mode.

  • In strict C++14 mode (-std=c++14 or -std=c++1y), the built-in extension must be disabled to remove ambiguity (as far as I can tell), hence both gcc and clang selecting the user-defined literal suffix.

  • In the gnu-extension-C++14 mode -std=gnu++14, gcc chooses the built-in suffix (for backwards-compatibility?), whereas clang chooses the user-defined suffix. This looks strange, and I'd suggest looking for or filing bug reports here.

Depending on which literal suffix is chosen, you either get the built-in type _Complex double or some std::complex<double>.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...