1

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 ?

Community
  • 1
  • 1
Barath Ravikumar
  • 5,658
  • 3
  • 23
  • 39
  • `C++00`? And I'm not sure what's the problem, given that you know about `std::complex`. – Kiril Kirov Mar 18 '14 at 14:58
  • 1
    `sed 's/float complex/std::complex/g'` – Angew is no longer proud of SO Mar 18 '14 at 15:00
  • What is the compilation error? AFAIK, although C++ has it's own `std::complex`, that shouldn't mean that old C libraries fail. I would have thought you just need to change that `#include` to include the C++ C-compatibility library. –  Mar 18 '14 at 15:00
  • @so the operations on "complex float" will work on " std::complex" ? – Barath Ravikumar Mar 18 '14 at 15:01
  • 1
    @Beagle Bone - I think not. The operations will be spelled differently, e.g. using operator overloading. Is the `complex` type you used in C part of the C standard? –  Mar 18 '14 at 15:05
  • If you want to stick with ``complex.h`` for the time being, post the actual compiler error here, so we have a chance to diagnose that problem. – Christian Aichinger Mar 18 '14 at 15:09
  • 2
    That error seems odd (and oddly mis-spelled - please cut-and-paste where possible), and check it's the error for the actual code you posted. An error along the lines of `not part of std` would make sense if your code had `std::complex` (and you hadn't included the right header - `` is different to ``), but doesn't make sense if you're referring to `complex` without mentioning `std`. –  Mar 18 '14 at 15:10
  • 2
    Is it strictly necessary to "port an enormous amount of C code to C++"? It's totally reasonable to just use a C compiler for the old stuff, C++ compiler for the new stuff, and let the linker deal with the details. – QuestionC Mar 18 '14 at 15:28

3 Answers3

5
#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;
}
Christian Aichinger
  • 6,989
  • 4
  • 40
  • 60
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
2

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));
}
bames53
  • 86,085
  • 15
  • 179
  • 244
1

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