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