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

查看:146
本文介绍了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 < 类型与预期相同<< endl;
    else
    cout<< 类型意外不同<< endl;

    cout<< 1.0i * 1.0i < endl;
    cout<<复合双(0.0,1.0)*复合双(0.0,1.0)< endl;
    }

    编译说明:

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

    输出:

     类型意外不一样
    1
    ,0)

    有趣的是,文字甚至不是一个适当的虚数。 (我相信我忽略了某些东西...)

    解决方案

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



    有一个 gcc扩展,用于生成 C99复数内置文字后缀 i 。这些是内置类型,例如 _Complex double ,而不是用户定义类(模板专用化)



    在C ++ 14中,C ++现在有一个用户定义的复杂数字的后缀 i 。也就是说,函数 complex< double>
    $ b中的 std :: literals :: complex_literals 内部命名空间中的运算符 $ b

    这两个字面后缀是竞争:




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


    • em> 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> p>

    Using gcc 4.9 I found that types generated with type literal for complex numbers are not the same as when created by conventional means, i.e.:

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

    1. Am I making a mistake here?
    2. Is this a compiler bug or intended standard behavior?
    3. If intended standard behavior: What is the rationale behind?

    Adding the missing 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;
    }
    

    Compile instructions:

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

    Output:

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

    Interestingly the literal does not even seem to be a proper imaginary number. (I am sure I am overlooking something...)

    解决方案

    The behaviour of the program depends on the language standard mode of gcc:

    There is a gcc extension for a built-in literal suffix i that produces C99 complex numbers. Those are distinct built-in types like _Complex double, as opposed to the "user-defined" class (template specialization) std::complex<double> used in C++.

    In C++14, C++ now has a user-defined literal suffix i for complex numbers. That is, a function complex<double> operator"" i(long double) within the std::literals::complex_literals inline namespace.

    Those two literal suffixes are competing:

    • In C++11 mode, only the built-in extension is possible, but it is an extension. Hence, gcc only allows it in -std=gnu++11 mode and even warns you about it. Strangely enough, clang allows it even in -std=c++11 mode.

    • In strict C++14 mode (-std=c++14 or -std=c++1y), the built-in extension must be disabled to remove ambiguity (as far as I can tell), hence both gcc and clang selecting the user-defined literal suffix.

    • In the gnu-extension-C++14 mode -std=gnu++14, gcc chooses the built-in suffix (for backwards-compatibility?), whereas clang chooses the user-defined suffix. This looks strange, and I'd suggest looking for or filing bug reports here.

    Depending on which literal suffix is chosen, you either get the built-in type _Complex double or some std::complex<double>.

    这篇关于typeid(complex&lt; double&gt;(0.0,1.0))!= typeid(1.0i)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆