Reputation: 5836
The code below runs fine in C. But in C++ (std-C++00), the compilation fails.
#include <complex.h>
int main()
{
float complex a = 0.0;
return 0;
}
Here's the errors i am facing
Error: complex is not pat of 'std'
Error: expected ';' before a
I have read the solution to the problem I am facing here, and I am also aware of std::complex.
But my problem is that, I must port an enormous amount of C code to C++, where complex numbers are declared and used, as shown above.
So any way of to do it ?
what other options do I have ?
Upvotes: 1
Views: 300
Reputation: 11
The answer from bames53 has been accepted and is very helpful. I am not able to add a comment to it, but I would suggest that perhaps
void print_sine(my_complex_type x) {
x = sin(x);
printf("%" PRI_complex_elem "+%" PRI_complex_elem "i\n", real(x), imag(x));
}
should use csin(x) in lieu of sin(x).
Upvotes: 1
Reputation: 88225
The C99 complex number syntax is not supported in C++, which instead includes the type std::complex
in the C++ standard library. You don't say what your motivation for porting the code is but there may be a couple different things you can do.
std::complex
is specified in C++11 to be layout compatible with C99's complex
. Implementations of earlier versions of C++ generally happen to provide std::complex
layout compatibility as well. You may be able to use this to avoid having to port most of the code. Simply declare the C code's interface in C++ such that C++ code can be linked to the C implementation.
#include <complex.h>
#ifdef __cplusplus
extern "C" void foo(std::complex<float>);
#else
void foo(complex float);
#endif
You may need to modify the above for your implementation. You have to ensure that both name mangling and calling conventions are consistent between the two declarations.
Alternatively, there are compilers that support the C complex syntax in C++ as an extension. Of course since the C complex
macro would interfere with std::complex
that macro does not get defined in C++ and you instead have to use the raw C keyword _Complex
. Or if you don't use std::complex
anywhere and you're never going to then you could just define the macro yourself: #define complex _Complex
.
#ifdef __cplusplus
#define complex _Complex
#else
#include <complex.h>
#endif
int main()
{
float complex a = 0.0;
return 0;
}
This #define
prohibits any use of the C++ complex headers. (and technically it causes undefined behavior if you make any use at all of the standard library, but as long as you avoid the headers <complex>
, <ccomplex>
, and <complex.h>
it will probably be okay in practice.
If you really do need to port the entire codebase to standard C++, you might consider porting it not directly to idiomatic C++, but instead to 'portable' C. I.e. code that compiles as both C and as C++. This way you can continue building as C while you incrementally port it and verify that it continues to work correctly throughout the porting process.
To do this you'll do things like replace float complex
with a typedef and then define the typedef appropriately in each language, use the C header <tgmath.h>
, define other macros in C to correspond with the C++ complex interface, etc.
#include <complex.h>
#include <math.h>
#ifdef __cplusplus
using my_complex_type = std::complex<float>;
#else
#include <tgmath.h>
typedef float complex my_complex_type;
#define real creal
#define imag cimag
#endif
#define PRI_complex_elem "f"
void print_sine(my_complex_type x) {
x = sin(x);
printf("%" PRI_complex_elem "+%" PRI_complex_elem "i\n", real(x), imag(x));
}
Upvotes: 2
Reputation: 227578
#include <complex>
int main()
{
// Both a and b will be initialized to 0 + 0i.
std::complex<float> a;
std::complex<float> b = 0.0f;
return 0;
}
Upvotes: 5