Bri*_*ian 2 c c++ complex-numbers
我正在使用 Apple LLVM 6.0 (clang-600.0.56)(基于 LLVM 3.5svn)在 OSX 上编译
具体来说,我正在尝试从 LibIIR 编译一个单一的源代码,LibIIR 是一个由 Laurence Withers在这里维护的过滤器库。
我已经看过这个答案在这里了有关同时使用<complex>,并<complex.h>在同一个文件。
我有一个iir.h像这样的文件:
#include <complex.h>
#ifdef __cplusplus
extern "C" {
#endif
...
Run Code Online (Sandbox Code Playgroud)
我有 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 {
...
Run Code Online (Sandbox Code Playgroud)
——
/*** iir++.h ***/
#include <complex>
namespace IIR {
...
Run Code Online (Sandbox Code Playgroud)
编译时clang给了我以下错误:
./iir.h:570:15: error: expected ';' after top level declarator
double complex iir_response_c(const struct iir_coeff_t* coeff, double freq);
^
;
Run Code Online (Sandbox Code Playgroud)
显然,新的<complex>导入没有发生——或者#undef complex再次发生——但我不明白是怎么回事。关于可能出什么问题或检查什么的任何建议?
<complex.h> 是一个 C 头文件,它与 C++ 不兼容。
C++ 通过在模式中命名的头文件定义 C 库兼容性<c***>。因此,与 C++ 对应<complex.h>的名称是<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
Run Code Online (Sandbox Code Playgroud)
请注意,根据 C++14 [complex.numbers] §26.4/4 和 C11 §6.2.5/13std::complex< double >与double complex布局兼容。意图似乎是您可以cdouble用于跨语言函数原型,尽管严格来说它取决于 ABI。
顺便说一句,C++ 标准确实定义了当你发生时会发生什么#include <complex.h>,但这没有任何意义:
每个 C 头文件,每个头文件都有一个形式为 的名称,其
name.h行为就好像由相应cname头文件放置在标准库名称空间中的每个名称都放置在全局名称空间范围内。未指定这些名称是否首先在命名空间的命名空间范围 (3.3.6) 中声明或定义std,然后通过显式using 声明(7.3.3)注入到全局命名空间范围中。
所以,#include <complex.h>应该给你一个全局的::complex<T>. 这是标准的缺陷。