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

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

本文关键字:typeid 0i gt complex lt double      更新时间:2023-10-16

使用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)

有趣的是,字面意思似乎甚至不是一个合适的虚数。(我确信我忽略了什么…)

程序的行为取决于gcc:的语言标准模式

内置文字后缀i的gcc扩展产生C99复数。与C++中使用的"用户定义"类(模板专用化)std::complex<double>不同,它们是类似_Complex double的独特的内置类型。

在C++14中,C++现在有一个用户定义的复数文字后缀i。也就是说,std::literals::complex_literals内联命名空间中的函数complex<double> operator"" i(long double)

这两个文字后缀相互竞争:

  • 在C++11模式中,只有内置扩展是可能的,但它的扩展。因此,gcc只在-std=gnu++11模式下允许它,甚至会警告你。奇怪的是,clang甚至在-std=c++11模式下也允许它。

  • strictC++14模式(-std=c++14-std=c++1y)中,必须禁用内置扩展以消除歧义(据我所知),因此gcc和clang都选择了用户定义的文字后缀。

  • 在gnu-extension-C++14模式-std=gnu++14中,gcc选择内置后缀(为了向后兼容性?),而clang选择用户定义的后缀。这看起来很奇怪,我建议在这里查找或提交错误报告。

根据所选择的文字后缀,您可以获得内置类型_Complex double或一些std::complex<double>