c ++和< complex.h>与< complex>在单独的文件 [英] c++ and <complex.h> with <complex> in separate files
问题描述
注意:
我正在使用Apple LLVM版本6.0(clang-600.0.56)(基于LLVM 3.5svn)在OSX上进行编译
具体来说,我试图从LibIIR编译一个整体源,一个过滤库,维护 我已经看过这个答案了。关于同时使用
< complex>
< complex.h>
设置:
我有一个文件 iir.h
>
#include< complex.h>
#ifdef __cplusplus
externC{
#endif
...
pre>
我有C ++源文件和头文件 libiir ++。cpp
和 iir ++。h
如下:
/ *** libiir ++。cpp *** /
我们需要首先包括iir.h,因为它拉入< complex.h> ;,其中我们需要
//在iir ++。h拉入< complex>
#includeiir.h
//现在删除复杂的预处理器定义到_Complex,这是罚款
//为C头,但不好的C ++ header
#undef complex
#includeiir ++。h
命名空间IIR {
...
-
*** iir ++。h *** /
#include< complex>
命名空间IIR {
...
问题:
clang在编译时给出以下错误:
./ iir.h:570:15:error:expected';'在顶级声明器之后
double complex iir_response_c(const struct iir_coeff_t * coeff,double freq);
^
;
显然,新的< complex>
导入不发生 - 或 #undef complex
再次发生 - 但我不知道如何。
解决方案 < complex.h> ;
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
时会发生什么,没有任何意义:
每个C头,每个头都有一个名为名称的名称。 h
,如同通过相应的 cname
头放置在标准库命名空间中的每个名称放置在全局命名空间范围。这些名称是否首先在命名空间 std
的命名空间范围(3.3.6)内声明或定义,然后通过显式的注入到全局命名空间范围中,使用声明(7.3.3)。
所以, #include& h>
应该给你一个全局 :: complex< T>
。这是标准中的缺陷。
Notes:
I am compiling on OSX using Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Specifically, I am trying to compile a monolithic source from LibIIR, a filter library maintained here by Laurence Withers.
I've already looked at this answer here about using both <complex>
and <complex.h>
in the same file.
Setup:
I have a file iir.h
like so:
#include <complex.h>
#ifdef __cplusplus
extern "C" {
#endif
...
I have C++ source and header files libiir++.cpp
and iir++.h
like so:
/*** 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 {
...
Problem:
clang gives me the following error when compiling:
./iir.h:570:15: error: expected ';' after top level declarator
double complex iir_response_c(const struct iir_coeff_t* coeff, double freq);
^
;
Evidently, the new <complex>
import is not happening--or #undef complex
is happening again--but I don't see how. Any advice on what might be going wrong, or what to check?
解决方案 <complex.h>
is a C header and it is not compatible with C++.
C++ defines C library compatibility through headers named in the pattern <c***>
. So, the C++ counterpart to <complex.h>
is named <ccomplex>
. Here's what the C++ standard has to say about that:
Header <ccomplex>
The header behaves as if it simply includes the header <complex>
.
If you attempt to use the C complex number library, you just get the C++ one instead.
Bottom line: you simply cannot run C complex math through a C++ compiler. At best, you can use the preprocessor to generate equivalent programs depending on __cplusplus
.
For example,
#if __cplusplus
# include <complex>
typedef std::complex< double > cdouble;
#else
# include <complex.h>
typedef double complex cdouble;
#endif
Note, std::complex< double >
and double complex
are layout-compatible per C++14 [complex.numbers] §26.4/4 and C11 §6.2.5/13. The intent seems to be that you can use cdouble
for cross-language function prototypes, although strictly speaking it depends on the ABI.
Incidentally, the C++ standard does define what happens when you #include <complex.h>
, but it doesn't make any sense:
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).
So, #include <complex.h>
should give you a global ::complex<T>
. This is a defect in the standard.
这篇关于c ++和< complex.h>与< complex>在单独的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!