[CM] s7_complex in C++

chohag at jtan.com chohag at jtan.com
Fri Oct 11 10:38:59 PDT 2024


bil at ccrma.Stanford.EDU writes:
> Which C++ compiler are you using?  The code works in g++.
> I'd try commenting out the typedef for s7_complex in the
> __cplusplus section (i.e. maybe your compiler wants the C
> form of the typedef).

$ c++ --version
OpenBSD clang version 16.0.6
Target: amd64-unknown-openbsd7.6
Thread model: posix
InstalledDir: /usr/bin

Aide-mémoire:

        #if (!__TINYC__)
          #if __cplusplus
            #include <complex>
            typedef std::complex<s7_double> s7_complex;
          #else
            #include <complex.h>
            typedef double complex s7_complex;
          #endif
        #else
            typedef double s7_complex;
        #endif

If I change line 21 to   #if __cplusplus && 0 then I get:

        ./s7.h:39:27: error: expected ';' after top level declarator
            typedef double complex s7_complex;
                                  ^
                                  ;

There are two problems here. First because s7.h declares functions
with C linkage, s7_complex' expansion to std::complex<s7_double>
cannot be used in a function signature.

Second C++ is doing magic. When <complex.h> is included, rather
than actually including complex.h, it knows better and reverts to
its own imagination which doesn't have a definition for complex.
It also doesn't bother declaring any of the functions that are
declared by that file. Because, again, the compiler knows better
than us that we don't want to be explicit about what types our
functions take but do love tracking down the precise collusion of
operator or function overloading that happen to be in play in *this*
line of code.

If I change the inclusion to "/usr/include/complex.h" then C++'s
sleight of hand is thwarted and we actually include the file we
asked for and 'double complex' is a valid type name again.

I understand that this behaviour is blessed by the standards committee.

I expect there is a right way to include C-linkage complex-returning
functions in a C++ compiler but I don't know what it is. There are
no useful examples in /usr/include/complex.h because C++ ignores
that. However this works well enough in a C header included from C++:

        typedef struct { double r, i; } s7_complex;

But then s7.o cannot be built by a C++ compiler.

On the other hand it apparently can't be built with this C++ compiler
anyway:

        s7.c:13811:84: error: invalid operands to binary expression ('_Complex double' and 's7_complex' (aka 'complex<double>'))
          static s7_complex casin(s7_complex z)  {return(-s7_complex_i * clog(s7_complex_i * z + csqrt(1.0 - z * z)));}
                                                                              ~~~~~~~~~~~~ ^ ~

Matthew




More information about the Cmdist mailing list