问题
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?
回答1:
<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 correspondingcname
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 namespacestd
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.
来源:https://stackoverflow.com/questions/31800065/c-and-complex-h-with-complex-in-separate-files