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

时间:2015-08-04 03:15:27

标签: c++ c complex-numbers

注意:

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

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

我已经在同一文件中查看了关于同时使用<complex><complex.h>的答案here

设置:

我有一个文件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再次发生 - 但我不知道如何。关于可能出现什么问题或者检查什么的任何建议?

1 个答案:

答案 0 :(得分:4)

<complex.h>是一个C头,它与C ++不兼容。

C ++通过模式<c***>中指定的标头定义C库兼容性。因此,<complex.h>的C ++对应名称为<ccomplex>。以下是C ++标准对此的评价:

  

标题<ccomplex>

     

标题的行为就像它只包含标题<complex>

如果您尝试使用C复数库,则只需使用C ++编号。

底线:您无法通过C ++编译器运行C复杂数学运算。最好的情况是,您可以使用预处理器根据__cplusplus生成等效的程序。

例如,

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

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

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

  

每个C标头(每个标头都具有name.h形式的名称)就好像每个名称由相应的 cname 标头放置在标准库名称空间中放在全局命名空间范围内。未指定是否首先在名称空间std的名称空间作用域(3.3.6)中声明或定义这些名称,然后通过显式 using-declarations 将其注入全局名称空间作用域(7.3 0.3)。

因此,#include <complex.h>应该为您提供全局::complex<T>。这是标准中的缺陷。