Mark K Cowan
Mark K Cowan

Reputation: 1863

C/C++ interop between _Complex and std::complex

I have some C DSP libraries which use complex [T] types for complex numbers. I want to call these from a C++ application which uses std::complex<T>.

After reading this SO answer and this one, and §26.4 of N4296, I tried an experiment:

extern "C" {
#include <complex.h>
// Using _Complex or __complex__ since C's "complex" type doesn't exist in C++
void cfunc(_Complex float x);
}
#include <complex>

void test()
{
        std::complex<float> z;
        cfunc(reinterpret_cast<float[2]>(z));
}

And tried to compile it with CXXFLAGS="-std=c++11". I got the following from GCC 6.3.1:

error: invalid cast from type ‘std::complex<float>’ to type ‘float [2]’
  cfunc(reinterpret_cast<float[2]>(z));

Is this a compiler bug or am I misunderstanding something? How would one use C functions which take complex [T] arguments, given C++ code using std::complex<T> types? Currently, I use a dirty hack to work around this issue but I'd prefer a clean way.

I tried compiling with -std=c++14 just in case this feature had missed C++11 somehow (despite posts quoting it from the C++11 standard) but I get the same result.


26.4 Complex numbers [complex.numbers]

  1. The header <complex> defines a class template, and numerous functions for representing and manipulating complex numbers.

  2. The effect of instantiating the template complex for any type other than float, double, or long double is unspecified. The specializations complex<float>, complex<double>, and complex<long double> are literal types (3.9).

  3. If the result of a function is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

  4. If z is an lvalue expression of type cv std::complex<T> then:

    4.1. the expression reinterpret_cast<cv T(&)[2]>(z) shall be well-formed,

    4.2. reinterpret_cast<cv T(&)[2]>(z)[0] shall designate the real part of z, and

    4.3. reinterpret_cast<cv T(&)[2]>(z)[1] shall designate the imaginary part of z.

Upvotes: 1

Views: 2377

Answers (1)

NathanOliver
NathanOliver

Reputation: 180500

You problem is you are trying to cast to a value instead of a reference. The standard guarantees that

reinterpret_cast<cv T(&)[2]>(z)

Is well formed. It does not say

reinterpret_cast<cv T[2]>(z)

Is valid. To make you code compile you need to change the cast to cast to a reference which gives you

cfunc(reinterpret_cast<float(&)[2]>(z));

Live Example

Upvotes: 5

Related Questions