12

を使用しgcc 4.9て、複素数の型リテラルで生成された型は、従来の手段で作成された場合と同じではないことがわかりました。

typeid(complex<double>(0.0,1.0)) != typeid(1.0i)
  1. 私はここで間違いを犯していますか?
  2. これはコンパイラのバグですか、それとも意図した標準的な動作ですか?
  3. 標準的な動作を意図している場合: 背後にある理論的根拠は何ですか?

不足している 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;
}

コンパイル手順:

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

出力:

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

興味深いことに、リテラルは適切な虚数ではないようです。(私は何かを見落としていると確信しています...)

4

1 に答える 1

20

プログラムの動作は、gccの言語標準モードによって異なります。

C99 複素数を生成する組み込みリテラル サフィックスのgcc 拡張機能iがあります。これらは、C++ で使用される「ユーザー定義」クラス (テンプレートの特殊化) とは対照的に、 のような別個の組み込み型です。_Complex doublestd::complex<double>

C++14 では、C++に複素数用のユーザー定義のリテラル サフィックスが追加されました。iつまり、インライン名前空間complex<double> operator"" i(long double)内の関数です。std::literals::complex_literals

これら 2 つのリテラル サフィックスは競合しています。

  • C++11モードでは組み込み拡張のみ可能ですが、拡張です。したがって、gcc は-std=gnu++11モードでのみ許可し、それについて警告することさえあります。奇妙なことに、clang は-std=c++11モードでもそれを許可します。

  • 厳密なC++14 モード (-std=c++14または)では-std=c++1y、(私が知る限り) あいまいさを取り除くために組み込みの拡張機能を無効にする必要があるため、gcc と clang の両方でユーザー定義のリテラル サフィックスが選択されます。

  • gnu-extension-C++14 モード-std=gnu++14では、gcc は組み込みのサフィックスを選択しますが (下位互換性のため?)、clang はユーザー定義のサフィックスを選択します。これは奇妙に思えます。ここでバグ レポートを探すか、提出することをお勧めします。

選択したリテラル サフィックスに応じて、組み込み型_Complex doubleまたは一部のstd::complex<double>.

于 2015-02-20T09:22:33.580 に答える