c++ 和 <complex.h> 与 <complex> 在单独的文件中

c++ and <complex.h> with <complex> in separate files

备注:

我正在 OSX 使用 Apple LLVM 版本 6.0 (clang-600.0.56)(基于 LLVM 3.5svn)进行编译

具体来说,我正在尝试从 LibIIR 编译单一源代码,这是一个由 Laurence Withers here 维护的过滤器库。

我已经看过这个答案 here 关于在 同一文件.[=25 中同时使用 <complex><complex.h> =]


设置:

我有一个文件 iir.h 像这样:

#include <complex.h>

#ifdef __cplusplus
extern "C" {
#endif

...

我有 C++ 源文件和头文件 libiir++.cppiir++.h,如下所示:

/*** libiir++.cpp ***/
// we need to include "iir.h" first, as it pulls in <complex.h>, which we need
// to take effect before "iir++.h" pulls in <complex>
#include "iir.h"

// now remove the preprocessor definition of complex to _Complex, which is fine
// for the C header but not good for the C++ header
#undef complex

#include "iir++.h"

namespace IIR {

...

-

/*** iir++.h ***/
#include <complex>

namespace IIR {

...

问题:

clang 在编译时给我以下错误:

./iir.h:570:15: error: expected ';' after top level declarator
double complex iir_response_c(const struct iir_coeff_t* coeff, double freq);
              ^
              ;

显然,新的 <complex> 导入没有发生——或者 #undef complex 又发生了——但我不知道如何发生。关于可能出现的问题或检查内容的任何建议?

<complex.h> 是 C 头文件,与 C++ 不兼容。

C++ 通过在模式 <c***> 中命名的头文件定义 C 库兼容性。因此,<complex.h> 的 C++ 对应项被命名为 <ccomplex>。以下是 C++ 标准对此的说明:

Header <ccomplex>

The header behaves as if it simply includes the header <complex>.

如果您尝试使用 C 复数库,您只需获取 C++ 库即可。

底线:您根本无法通过 C++ 编译器 运行 C 复杂数学。充其量,您可以使用预处理器根据 __cplusplus.

生成等效程序

例如,

#if __cplusplus
#   include <complex>
    typedef std::complex< double > cdouble;
#else
#   include <complex.h>
    typedef double complex cdouble;
#endif

注意,根据 C++14 [complex.numbers] §26.4/4 和 C11 §6.2.5/13,std::complex< double >double complex 布局兼容。其意图似乎是您可以将 cdouble 用于跨语言函数原型,尽管严格来说它取决于 ABI。


顺便说一句,C++ 标准确实定义了当您 #include <complex.h> 时会发生什么,但它没有任何意义:

Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).

所以,#include <complex.h> 应该给你一个全局 ::complex<T>。这是标准的缺陷。