6
\$\begingroup\$

Motivation

I typically try to avoid using ! in if-statements, because (to me) it seems easy to overlook. So, I'll usually just spell it out instead, ex: if (done == false) instead of if (!done). While that makes the intention more obvious, it doesn't read very fluidly.

Macro code

For those cases I wrote the following macro:

#define NOT(x) ((x) == false)

The outer parentheses make it possible to use NOT(cond) without additional parentheses in if and make it less error prone:

if NOT(condition) {
    ...
}

Complete example of macro usage

#include <iostream>

#define NOT(x) ((x) == false)

bool successful() {return false;}

int main(int argc, char **argv)
{
    if NOT(successful()) {
        std::cout << "Warning! Self-destruction activated...\n";
    }

    const bool this_is_true = true;

    if NOT(this_is_true) {
        std::cout << "True is false.\n";
    }

    return EXIT_SUCCESS;
}

Concerns

While this works, I have some concerns:

  1. From a best-practices or clean code perspective, is this frowned upon?

  2. How are macros generally viewed, or reported on, in code analysis tools? We are considering employing a system called CAST-AIP for code analysis and, while I am strongly in favor of doing so, I am wondering how many volumes of practice violations my reports are going to be.

\$\endgroup\$
  • 12
    \$\begingroup\$ Best: Never use macros at all with c++. Don't obfuscate semantics. \$\endgroup\$ – πάντα ῥεῖ Apr 13 '18 at 18:01
  • 2
    \$\begingroup\$ @πάνταῥεῖ there are some very, very, very rare cases where macros can improve code quality and the alternative is more error prone than the macro. This isn't one of them. \$\endgroup\$ – Zeta Apr 13 '18 at 18:05
  • 4
    \$\begingroup\$ I'm not sure what more context one can provide here... this question shouldn't have been closed. It's a simple, one-liner macro, what else one can say about it but providing an example? \$\endgroup\$ – t3chb0t Apr 13 '18 at 18:08
  • 2
    \$\begingroup\$ From codereview.stackexchange.com/help/dont-ask: "Best practices in general: It's OK to ask "Does this code follow common best practices?"" \$\endgroup\$ – Blair Fonville Apr 13 '18 at 18:14
  • 2
    \$\begingroup\$ Close-reason discussion on meta \$\endgroup\$ – t3chb0t Apr 13 '18 at 18:16
22
\$\begingroup\$

Something like if (foo == false) will always be frowned upon. If you find the negation hard to spot you might consider using not instead (see this for more info).
E.g. if (not foo)

From what I've seen macros are generally discouraged as they tend to obfuscate code and are not typesafe.

\$\endgroup\$
  • \$\begingroup\$ I don't see any sense in waiting to accept this. I can't believe I never knew about these alternative operators. One thing that confuses me is where it reads: "Because in C++ these are built into the language, the C++ version of <iso646.h>, as well as <ciso646>, does not define anything.". Yet it doesn't appear to work without including one. \$\endgroup\$ – Blair Fonville Apr 13 '18 at 18:48
  • \$\begingroup\$ @BlairFonville MSVC? AFAIK they don't (or at least didn't) implement that correctly. You can probably use /FI (force include) to make it work without it. \$\endgroup\$ – Justin Apr 13 '18 at 19:49
  • \$\begingroup\$ @Justin You guessed it, VS2017. When I followed the not operator, I found that it resolves to iso646.h : #define not !. Where iso646.h, is included in their ciso646 header. I'll look into /FI, but from it's name, it sounds like it just going to save me the one "#include <ciso646>" line, by doing it for me. \$\endgroup\$ – Blair Fonville Apr 13 '18 at 19:58
  • \$\begingroup\$ @BlairFonville Yes, that's what it would do. The good thing about that is that it would improve the quality of the code, as your build system would be taking care of the non-standard stuff. \$\endgroup\$ – Justin Apr 13 '18 at 20:02
  • 1
    \$\begingroup\$ For some reason habits that hinder readability are traditional and very tenacious in the C/C++ world. The keywords not, and and or (as well as several others) as alternative representations of !, && and || exist for ages, but few seem to know about them, let alone use them; personally I always use them (except then && means "rvalue reference"). I also always avoid implicit conversion from int to bool (writing if (i!=0) if that is what I mean), though that does not prevent me from occasionally getting bitten by an unintended implicit conversion. \$\endgroup\$ – Marc van Leeuwen Apr 14 '18 at 6:58
-4
\$\begingroup\$

why not just

#define NOT !

It would be simpler to use.

\$\endgroup\$
  • 3
    \$\begingroup\$ or just #include<iso646.h>, which does precisely that - per the discussion in comments of yuri’s answer. \$\endgroup\$ – Blair Fonville Apr 14 '18 at 2:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.