2015-02-20 3 views
11

gcc 4.9 Verwendung fand ich, dass mit Typ-generierten Typen wörtlichen für komplexe Zahlen sind nicht das gleiche wie wenn sie durch herkömmliche Mittel geschaffen, das heißt:typeid (komplexe <double> (0.0,1.0)) = typeid (1.0i)

typeid(complex<double>(0.0,1.0)) != typeid(1.0i) 
  1. Mache ich hier einen Fehler?
  2. Ist dies ein Compilerfehler oder beabsichtigtes Standardverhalten?
  3. Wenn beabsichtigtes Standardverhalten: Was ist der Grund dafür?

die fehlenden MCVE Hinzufügen

#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 Anweisungen:

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

Ausgang:

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

Interessanterweise ist die wörtliche scheint nicht einmal eine richtige imaginäre Zahl zu sein. (Ich bin sicher, ich bin etwas mit Blick auf ...)

+0

Gibt es eine Chance, dass Sie das in eine Quellliste, die tatsächlich kompiliert? Ich denke * du verwendest 'std :: complex ', was anders ist als '_Complex', die gnu-Erweiterung für imaginäre Konstanten, aber ohne MCVE ist es schwer zu sagen * was * du eigentlich machst. – WhozCraig

+0

Danke für das Update. Ja, sie sind verschiedene Arten. Once stammt aus der Standardbibliothek, der andere aus einer Compiler-Erweiterung. – WhozCraig

+2

[Das Problem kann nicht in C++ reproduziert werden 14] (http://coliru.stacked-crooked.com/a/1fbd46340ab9b14e) @WhozCraig Das 'i' ist (auch?) Ein literales Suffix in C++ 14. Im C++ 11-Modus verwendet gcc wahrscheinlich [diese Erweiterung] (https://gcc.gnu.org/onlinedocs/gcc/Complex.html) – dyp

Antwort

20

Das Verhalten des Programms hängt von dem Sprache Standardmodus von gcc:

Es gibt ein gcc extension for a built-in literal suffix i die C99 komplexe Zahlen produziert. Das sind verschiedene eingebaute Typen wie _Complex double, im Gegensatz zu der "benutzerdefinierten" Klasse (Template-Spezialisierung) std::complex<double> in C++ verwendet.

In C++ 14 hat C++ jetzt eine benutzerdefinierte Literal Suffix i für komplexe Zahlen. Das heißt, eine Funktion complex<double> operator"" i(long double) innerhalb des std::literals::complex_literals Inline-Namensraums.

Diese beiden wörtlichen Suffixe konkurrieren:

  • In C++ 11-Modus, nur der Einbau-Erweiterung ist möglich, aber es ist eine Erweiterung. Daher erlaubt gcc es nur in -std=gnu++11 Modus und warnt Sie sogar davor. Seltsamerweise erlaubt clang es sogar in -std=c++11 Modus.

  • In strengen C++ 14-Modus (-std=c++14 oder -std=c++1y), die sich im internen Verlängerung muss deaktiviert werden, um Unklarheiten zu beseitigen (soweit ich sagen kann), also sowohl gcc und Klappern der Auswahl der benutzerdefinierten Literales Suffix.

  • Im gnu-extension-C++ 14-Modus -std=gnu++14 wählt gcc das eingebaute Suffix (für Abwärtskompatibilität?), Während clang das benutzerdefinierte Suffix auswählt. Das sieht seltsam aus, und ich würde vorschlagen, hier nach Fehlerberichten zu suchen oder diese zu archivieren.

Je nachdem, auf dem wörtlichen Suffix, die Sie gewählt entweder bekommen die eingebauten Typen _Complex double oder ein std::complex<double>.

+0

Hervorragende Antwort. Ich vergesse immer wieder, dass benutzerdefinierte Literale unter den Schirm kamen. – WhozCraig