c++ and <complex.h> with <complex> in separate files

旧街凉风 提交于 2019-12-20 02:56:38

问题


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 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.



来源:https://stackoverflow.com/questions/31800065/c-and-complex-h-with-complex-in-separate-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!