(Follow-up of Overload ternary ?: operator, or change to if{}else{} in included files.)
Context
Research project here. In my C++ library, I am including C files using #include "aprogram.c" which I execute symbolically by overloading (almost) all operators.
I have to be able to detect (condition) ? this : that and extract condition, this and that for usage in my symbolic execution library, for the following cases:
(a >= 0) ? a : -a
(a >= b) ? a : b
Conceptual question
Because I cannot overload the ternary ?: operator in C++, and it only has to work for the above cases, can't I 'overload' them by using macros somewhat like:
#define TO_NEG(a) ((a >= 0) ? a : -a)
#define MAX(a,b) ((a >= b) ? a : b)
and implement TO_NEG(a) and MAX(a,b)?
Edit: Clarification
With this, I want to achieve that my library
detects ?: in both cases
converts it to TO_NEG or MAX
uses new code I wrote for TO_NEG and MAX
Assuming your operator >= produces a MyBool type, I think you can get almost there with:
#define ? .ternary(
#define : )||
template <typename T>
T MyBool::ternary(T val) {
if (m_isTrue) return val;
return T(0)
}
Several things to note:
This doesn't work for a>=b if a is 0 and b is negative.
This is a terrible terrible hack that will break on many edge cases.
You can't actually use : as a symbol in a #define, so you'd have to use some other means of replacing them, at which point, you should probably use something like #raxvan's answer
You can define something that will replace the ? operator inside the c source file.
The closest thing you can do is the following:
#define QUESTION_OPERATOR(COND,THIS,THAT) ((COND) ? (THIS) : (THAT))
//here you can do custom validations to all the parts if you want
usage:
(cond) ? (This) : (That) //you need to replace this with:
QUESTION_OPERATOR(cond,This,That)
Yes, you can use the ternary operator in macros, but they must be correctly parenthesized:
#define TO_NEG(a) (a >= 0) ? (a) : -(a)
#define MAX(a,b) (a >= b) ? (a) : (b)
Related
Here is a snippet of a pseudocode from a friend.
int a=50, b=20, c=10;
if (b=(b>a ? a:c))
c = a - b;
What does the code b>a ? a:c mean exactly?
It's called a conditional or ternary Operator.
It's similar to an if-else statement (short hand if Else). For example, here b>a ? a : c if b > a then it returns a else it returns c.
For more info just google it.
I have a habit of using the following syntax in my compile-time flags:
#if (defined(A) & defined(B))
It's usually suggested that I do it with the && as follows:
#if (defined(A) && defined(B))
I know the difference between the two operators, and that in normal code && would short-circuit. However, the above is all handled by the compiler. Does it even matter what I use? Does it affect compile time by some infinitesimal amount because it doesn't evaluate the second define()?
Since defined(SOMETHING) yields 0 or 1, so that you're guaranteed 0 or 1 on both sides, it doesn't make a technical difference whether you use & or &&.
It's mostly about good habits (using & could carry over to some situation where it would be wrong) and about writing code that is easy to grasp by simple pattern matching. A & in there causes a millisecond pause while one considers whether it possibly could be a bit-level thing.
On the third hand, you can't use keyword and, which you ¹can use in ordinary C++ code.
Notes:
¹ With Visual C++ you can use and via a forced include of <iso646.h>.
According to the C99 standard, the expressions used in the preprocessor are constant expressions as defined by the C language itself, and are evaluated using the same engine. Therefore, && is a logical and operator that short circuits based on its LHS, and & is a bitwise operator with no predefined order of evaluation.
In practical terms, when used with defined() as you are, there is no difference between the two. However, the following would show a difference:
#define A 2
#define B 5
#if (A && B)
printf("A && B\n");
#endif
#if (A & B)
printf("A & B"\n);
#endif
In this case, A && B will be output, but not A & B (since the result of that bitwise-and is 0)
I would like to add to the previous answers that it can actually matter a lot in a situation like this:
#define A 0
#define B 21
#if (A != 0) && (42 / A == B)
/* ... */
#endif
Here, if A == 0, the compiler will not break. Writing (A != 0) & (42 / A == B) will make the compiler complain about a division by zero.
I have started reading Effective C++ and at some point in item 2, the following is mentioned:
// call f with the maximum of a and b
#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
...
int a = 5, b = 0;
CALL_WITH_MAX(++a, b); // a is incremented twice
CALL_WITH_MAX(++a, b+10); // a is incremented once
Here, the number of times that a is incremented before calling f
depends on what it is being compared with!
Indeed, if I use a simple print statement in f, 7 gets printed in the first call, but I cannot for the life of me figure out why. Am I missing something obvious?
The compiler replaces the macros with exactly what you pass in, verbatim. So you end up with
int a = 5, b = 0;
f((++a) > (b) ? (++a) : (b));
f((++a) > (b+10) ? (++a) : (b+10));
Use g++ -E myprog.cpp (replace g++ with whatever-your-compiler-is if you are not using g++) - it works on ALMOST all compilers, it will produce the actual stuff after preprocessing.
And this is a great example of why you shouldn't use macros to do function-type stuff.
You'd get much more of what you (probably) expect if you were to use an inline function:
inline void CallWithMax(int a, int b)
{
f((a) > (b) ? (a) : (b));
}
Any decent compiler should be able to do this AT LEAST as efficient as a macro, with the added advantage that your a and b are evaluated once in the calling code, and nothing "weird" happens.
You can also step through a inline function if you build your code with debug symbols, so if you want to see what value a and b actually are inside the function, you can do that. Macros, because they expand into the original place in the source code, so you can't really see what's going on inside.
I have define the following macro,
#define abss(a) a >= 0 ? a : -a
while invoking this with,
int b=-1;
int c = abss(b);
printf("%d\n",c);
it should replaced in the form b >= 0 ? b : --b, which should output -2, but it outputs in my Bloodshed/DevC++ compiler 1.
I am analyzing C language for examination purpose, so I have to know what actually happens to the above case in C. Is the output result 1 is for CPP compiler I am using or what???
Your code
int b=-1;
int c = abss(b);
printf("%d\n",c);
gets translated by the preprocessor to:
int b=-1;
int c = b >= 0 ? b : -b;
printf("%d\n",c);
(the int b=-1 is in the C domain whereas the abss(b) gets expanded by the preprocessor before the compiler gets to int b=-1)
Why on earth do you think it should output -2?
#define abss(a) a >= 0 ? a : -a
so this:
int c = abss(b)
becomes
int c = b >= 0 ? b : -b
and b is -1, so that will evaluate to 1
by the way, you should bracket every use of a macro parameter, as you may get passed such things as x + 1. which would evaluate rather strangely.
Not to mention the results of abss(++x)
Your macro expands to
b >= 0 ? b : -b;
Not to b >= 0 ? b : --(-b); or whatever it is you expected.
Are you suggesting that
int x = -4;
-x;
should decrement x?
Bottom line - avoid macro use when possible.
The macro processor will never attach two adjacent tokens together, even if there is no whitespace between them, so indeed, as other posters have mentioned, your macro expands to - b, or 1.
If you want two tokens to become one when expanded by the preprocessor, you have to use the token pasting operator ##, something like
#define abss(a) a >= 0 ? a : - ## a
this will indeed do what you want, in the sense that the negative sign and the variable will form one token. Unfortunately (or fortunately, depending on how you look at it!) the pasted token "-b" will be invalid, and the expansion will not compile.
#define neg(a) -a
int b = -1;
neg(b);
In the above case, the macro is expanded to -b by the preprocessor, which will result in the value of 1. The preprocessor won't even be aware that the sign of the content of b is negative, so where should the second - come from to form a prefix decrement operator?
Even if you wrote it like this:
neg( -b );
Macro replacement is done on token level, not as a textual search & replace. You would get the equivalent of - ( -b ), but not --b.
Edit: The manual you link to in other comments is outdated (does not even address the C99 standard), and is dangerously bad. Just skimming through it I found half a dozen of statements that will make you look real stupid if you assume them to be correct. Don't use it, other than to light a fire.
This macro
#define abss(a) a >= 0 ? a : -a
is indeed hazardous, but the hazards are not where you think they are. The expression from your post
int c = abss(b);
works perfectly fine. However, consider what happens when the expression is not a simple variable, but is a function that is hard to calculate, or when it is an expression with side effects. For example
int c = abss(long_calc(arg1, arg2));
or
int c = abss(ask_user("Enter a value"));
or
int c = abss(b++);
If abss were a function, all three invocations would produce good results in predictable time. However, the macro makes the first call invoke long_calc and ask_user twice (what if the user enters a different number when prompted again?), and it post-increments b twice.
Moreover, consider this seemingly simple expression:
int c = abss(b) + 123;
Since + has a higher precedence than ? :, the resulting expansion will look like this:
int c = b >= 0 ? b : -b + 123;
When b is positive, 123 will not be added, so the meaning of the expression will change dramatically!
This last shortcoming can be addressed by enclosing the expression in parentheses. You should also enclose in parentheses each macro argument, like this:
#define abss(a) ((a) >= 0 ? (a) : -(a))
The reason for you getting the behaviour is preprocessor will just replace a with b and so effectively your code after preprocessing will be like
b >= 0 ? b : -b
and not
b >= 0 ? b : --b
So, when if b = -1, then it will effectively be considered as -(-1) and thus becomes 1.
You can check the preprocessor output and see it for yourself.
[This question is related to but not the same as this one.]
If I try to use values of certain types as boolean expressions, I get a warning. Rather than suppress the warning, I sometimes use the ternary operator (?:) to convert to a bool. Using two not operators (!!) seems to do the same thing.
Here's what I mean:
typedef long T; // similar warning with void * or double
T t = 0;
bool b = t; // performance warning: forcing 'long' value to 'bool'
b = t ? true : false; // ok
b = !!t; // any different?
So, does the double-not technique really do the same thing? Is it any more or less safe than the ternary technique? Is this technique equally safe with non-integral types (e.g., with void * or double for T)?
I'm not asking if !!t is good style. I am asking if it is semantically different than t ? true : false.
The argument of the ! operator and the first argument of the ternary operator are both implicitly converted to bool, so !! and ?: are IMO silly redundant decorations of the cast. I vote for
b = (t != 0);
No implicit conversions.
Alternatively, you can do this: bool b = (t != 0)
Careful!
A boolean is about truth and falseness.
An integer is about whole numbers.
Those are very distinct concepts:
Truth and falseness is about deciding stuff.
Numbers are about counting stuff.
When bridging those concepts, it should be done explicitly. I like Dima's version best:
b = (t != 0);
That code clearly says: Compare two numbers and store the truth-value in a boolean.
All valid techniques, all will generate the same code.
Personally, I just disable the warning so I can use the cleanest syntax. Casting to a bool is not something I'm worried about doing accidentally.
Yes it is safe.
0 is interpreted as false, everthing else is true,
hence !5 comes out as a false
!0 comes out as true
so !!5 comes out as true
I would not use:
bool b = !!t;
That is the least readable way (and thus the hardest to maintain)
The others depend on the situation.
If you are converting to use in a bool expression only.
bool b = t ? true : false;
if (b)
{
doSomething();
}
Then I would let the language do it for you:
if (t)
{
doSomething();
}
If you are actually storing a boolean value. Then first I would wonder why you have a long in the first places that requires the cast. Assuming you need the long and the bool value I would consider all the following depending on the situation.
bool b = t ? true : false; // Short and too the point.
// But not everybody groks this especially beginners.
bool b = (t != 0); // Gives the exact meaning of what you want to do.
bool b = static_cast<bool>(t); // Implies that t has no semantic meaning
// except as a bool in this context.
Summary:
Use what provides the most meaning for the context you are in.
Try and make it obvious what you are doing
I recommend never suppressing that warning, and never using a c cast (bool) to suppress it. The conversions may not always be called as you assume.
There is a difference between an expression that evaluates to true and a boolean of that value.
Both !! and ternary take getting used to, but will do the job similarly, if you do not want to define internal types with overloaded casts to bool.
Dima's approach is fine too, since it assigns the value of an expression to a bool.
If you're worried about the warning, you can also force the cast: bool b = (bool)t;
I really hate !!t!!!!!!. It smacks of the worst thing about C and C++, the temptation to be too clever by half with your syntax.
bool b(t != 0); // Is the best way IMHO, it explicitly shows what is happening.
Comparison to 0 doesn't work so well.
Which comes back -- why !! vs. ternary?
class foo { public: explicit operator bool () ; };
foo f;
auto a = f != 0; // invalid operands to binary expression ('foo' and 'int')
auto b = f ? true : false; // ok
auto c = !!f; // ok
!! may be compact, but I think it is unnecessarily complicated. Better to disable the warning or use the ternary operator, in my opinion.
I would use b = (0 != t) -- at least any sane person can read it easily. If I would see double dang in the code, I would be pretty much surprised.
Disable the warning.
Write for clarity first; then profile; then optimize for speed, where required.
!! is only useful when you're using a boolean expression in arithmetic fashion, e.g.:
c = 3 + !!extra; //3 or 4
(Whose style is a different discussion.) When all you need is a boolean expression, the !! is redundant. Writing
bool b = !!extra;
makes as much sense as:
if (!!extra) { ... }
I recommend to use
if (x != 0)
or
if (x != NULL)
instead of if(x); it's more understandable and readable.
The double not feels funny to me and in debug code will be very different than in optimized code.
If you're in love with !! you could always Macro it.
#define LONGTOBOOL(x) (!!(x))
(as an aside, the ternary operator is what I favor in these cases)
I would use bool b = t and leave the compile warning in, commenting on this particular line's safety. Disabling the warning may bite you in the butt in another part of the code.