C++ 11的不同编译器行为

Big*_*awg 1 g++ icc complex-numbers c++11 clang++

以下代码

#include <vector>
#include <complex>
#include <algorithm>

template<class K>
inline void conjVec(int m, K* const in) {
    static_assert(std::is_same<K, double>::value || std::is_same<K, std::complex<double>>::value, "");
    if(!std::is_same<typename std::remove_pointer<K>::type, double>::value)
#ifndef OK
        std::for_each(in, in + m, [](K& z) { z = std::conj(z); });
#else
        std::for_each(reinterpret_cast<std::complex<double>*>(in), reinterpret_cast<std::complex<double>*>(in) + m, [](std::complex<double>& z) { z = std::conj(z); });
#endif
}

int main(int argc, char* argv[]) {
    std::vector<double> nums;
    nums.emplace_back(1.0);
    conjVec(nums.size(), nums.data());
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

用Linux编译好

  1. Debian clang版本3.5.0-9
  2. gcc版本4.9.1
  3. icpc版本15.0.1

在Mac OS X上

  1. gcc版本4.9.2

但没有

  1. 铛,600.0.56
  2. icpc版本15.0.1

除非OK定义了宏.我不知道哪些是错误的编译器,有人能告诉我吗?谢谢.

PS:这是错误

10:48: error: assigning to 'double' from incompatible type 'complex<double>'
        std::for_each(in, in + m, [](K& z) { z = std::conj(z); });
Run Code Online (Sandbox Code Playgroud)

Seb*_*edl 5

不同的是,在Linux上,您使用的是libstdc ++和glibc,而在MacOS上,您使用的是libc ++以及CRT MacOS使用的任何内容.

MacOS版本是正确的.(此外,您的解决方法完全被破坏并且非常危险.)

这就是我认为发生的事情.

环境中存在多个重载conj.C++ 98引入了一个模板,它接受std::complex<F>并返回相同的类型.因为这个模板需要F进行推断,当调用它不工作conj与简单的浮点数,所以C++ 11加入的重载conj内搭float,doublelong double,并返回相应的std::complex实例.

然后是C99库中的全局函数::conj,它接受C99 double complex并返回相同的值.

conj就我所见,libstdc ++尚未提供新的C++ 11 重载.conj不调用C++版本.然而,似乎以某种方式::conj找到了进入std命名空间的方式,并被调用.的double传递被隐式转换为double complex通过添加零虚数部分.conj否定那个零.通过丢弃虚构组件将结果double complex隐式转换回a double.(是的,这是C99中的隐式转换.不,我不知道他们在想什么.)结果可以分配给z.

libc ++提供了新的重载.所述一个采取一个double被选择.它返回一个std::complex<double>.此类没有隐式转换double,因此赋值z给您一个错误.

最重要的是:你的代码完全没有意义.A vector<double>不是vector<complex<double>>,不应该被视为一个.调用conjdouble没有意义.要么它不编译,要么它是无操作.(conj(double)实际上,libc ++ 是通过简单地构造一个complex<double>零虚部来实现的.)并且疯狂地reinterpret_cast编译错误是非常可怕的.