c – typeid(complex(0.0,1.0))!= typeid(1.0i)

使用 gcc 4.9我发现使用类型文字生成的复数类型与通过常规方法创建的类型不同,即:
typeid(complex<double>(0.0,1.0)) != typeid(1.0i)

在这里犯错吗?
这是编译器错误还是想要的标准行为?
>如果想要标准行为:背后的理由是什么?

添加缺少的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的语言标准模式:

一个gcc extension for a built-in literal suffix i产生C99复数.这些是类似_Complex double的不同内置类型,而不是“用户定义的”类(模板专用)std :: complex< double>用于C.

在C 14中,C现在有一个用户定义的文字后缀i用于复数.也就是说,功能复合体< double>运算符“”i(long double)在std :: literals :: complex_literals内联命名空间中.

这两个字面的后缀是竞争的:

>在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.

相关文章

对象的传值与返回说起函数,就不免要谈谈函数的参数和返回值...
从实现装饰者模式中思考C++指针和引用的选择最近在看...
关于vtordisp知多少?我相信不少人看到这篇文章,多半是来自...
那些陌生的C++关键字学过程序语言的人相信对关键字并...
命令行下的树形打印最近在处理代码分析问题时,需要将代码的...
虚函数与虚继承寻踪封装、继承、多态是面向对象语言的三大特...