typeid(复杂<double>(0.0,1.0)) != typeid(1.0i)
typeid(complex<double>(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
,与C++中使用的"user-defined"class(模板专业化)std::complex<double>
相反.
在 C++14 中,C++ 现在有一个用于复数的 用户定义 文字后缀 i
。也就是说,std::literals::complex_literals
内联命名空间中的函数 complex<double> operator"" i(long double)
。
这两个字面后缀在竞争:
在C++11模式下,只有内置扩展是可能的,但是扩展。因此,gcc 只允许在 -std=gnu++11
模式下使用它,甚至会警告您。奇怪的是,即使在 -std=c++11
模式下,clang 也允许它。
在strict C++14模式(-std=c++14
或-std=c++1y
)中,必须禁用内置扩展才能消除歧义(据我所知),因此 gcc 和 clang 都选择了用户定义的文字后缀。
在gnu-extension-C++14模式下-std=gnu++14
,gcc选择内置后缀(为了向后兼容?),而clang选择用户定义的后缀.这看起来很奇怪,我建议您在此处查找或提交错误报告。
根据选择的文字后缀,您可以得到内置类型 _Complex double
或某些 std::complex<double>
.
使用 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
,与C++中使用的"user-defined"class(模板专业化)std::complex<double>
相反.
在 C++14 中,C++ 现在有一个用于复数的 用户定义 文字后缀 i
。也就是说,std::literals::complex_literals
内联命名空间中的函数 complex<double> operator"" i(long double)
。
这两个字面后缀在竞争:
在C++11模式下,只有内置扩展是可能的,但是扩展。因此,gcc 只允许在
-std=gnu++11
模式下使用它,甚至会警告您。奇怪的是,即使在-std=c++11
模式下,clang 也允许它。在strict C++14模式(
-std=c++14
或-std=c++1y
)中,必须禁用内置扩展才能消除歧义(据我所知),因此 gcc 和 clang 都选择了用户定义的文字后缀。在gnu-extension-C++14模式下
-std=gnu++14
,gcc选择内置后缀(为了向后兼容?),而clang选择用户定义的后缀.这看起来很奇怪,我建议您在此处查找或提交错误报告。
根据选择的文字后缀,您可以得到内置类型 _Complex double
或某些 std::complex<double>
.