Reputation: 105
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
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
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
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:
absolute
, myAbs
etc...myNameSpace::abs(x)
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
Reputation: 87944
Use #undef
#include "header1.h"
#include "header2.h"
#undef abs // remove abs macro
x = std::abs(y);
Upvotes: 6