我正在使用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++.cpp
和iir++.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
再次发生 - 但我不知道如何。关于可能出现什么问题或者检查什么的任何建议?
答案 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>
。这是标准中的缺陷。