user2194381
user2194381

Reputation: 105

Using the function of a specific library

I have a problem: I would like to use the function abs of the library complex.

However, I undergo an error warning me the function abs used is #define abs(x) (x > 0) ? x : -(x).

Thus, I think the problem comes from my imports. Because of I also include the stdio and stdlib libraries, the compiler may use the function abs defined in one of these libraries.

So my question is: how can I use the function abs of the library complex without removing any import ?

Thanks a lot in advance for your response.

Upvotes: 4

Views: 743

Answers (4)

luser droog
luser droog

Reputation: 19484

Wrap parens around it.

(abs)(whatever);

This will force the compiler to use the function version because the macro no longer matches.

Function-like macros work by matching an identifier followed by a left paren (. Since we've wrapped the function name itself in parens, we have instead an identifier followed by a right paren ), which fails to match the macro. The parens are semantically transparent, but they inhibit the macro syntax.

IIRC, it was splint the C checker which taught this to me. While writing a postscript interpreter, I created nice short macros to access the stack.

#define push(o) (*tos++ = (o))
#define pop() (*--tos)

Which were great until the tricky parts where they were part of an expression involving tos. To avoid undefined behavior, I had to create function versions and use those for those tricky spots. For the new design, I skipped the macros altogether.


Edit: I've got a nagging feeling that it was actually the Coelocanthe book (Peter Van Der Linden's Deep C Secrets) where I learned this, the above situation being where I first needed it. IIRC his example involved putchar or getchar which are often implemented as both functions and macros in conforming C implementations.

Upvotes: 15

Mats Petersson
Mats Petersson

Reputation: 129314

Whilst several suggestions above are very good, I would take a completely different angle. It is almost certainly something like windows.h that causes the "bad" macro definition of abs(). You should be able to NOT include "windows.h" in the file that does the complex math [in most types of programs, at least] (I'm not aware of a single function in Windows that takes complex<T> as an argument, so I'm pretty certain you don't need both "complex.h" and "windows.h" in the same source file. This method is called "isolating the system dependencies", and doing that is a very good thing.

Have a look at your code, and find where you are ACTUALLY using windows functions, and then only include "windows.h" in the files that actually need it. You'll probably find, if you are using Visual Studio, that "windows.h" is included as part of "stdafx.h", which means that all sort of interesting macros etc are being included all over the place, because "stdafx.h" is included in ALL source files.

Upvotes: 4

Roee Gavirel
Roee Gavirel

Reputation: 19445

Both #undef and parentheses solutions will work but I would advise to have something a little stronger, because both those solutions will required you to do them every time you want to call abs and next time you may forget and result in a bug.

what you can do:

  1. change the name of your function to less common name : absolute, myAbs etc...
  2. put you function\class under a name space (for C++ not for C) then the calls are explicit myNameSpace::abs(x)
  3. If it won't work as the comment here suggested I would still warp the call in my function:

    type myAbs(type param) { return (abs)(param); }

Upvotes: 1

john
john

Reputation: 87944

Use #undef

#include "header1.h"
#include "header2.h"
#undef abs // remove abs macro

x = std::abs(y);

Upvotes: 6

Related Questions