????R0
if !(condition)

New Proposal,

This version:
https://github.com/YexuanXiao/if-not/blob/master/proposal.bs
Author:
Audience:
SG17
Project:
ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21

Abstract

Allow if !(condition).

1. Motivation

When using a logical operator to combine two conditions and then inverting it, the user must enclose the combined condition in parentheses.

if (!(cond1 && cond2))

This pattern appears about 1500 times in LLVM, and about 2300 times in GCC. Excessive parentheses is annoying, some users might opt to use macros to simplify this, but macros are clearly not an ideal solution: they lack scope, and their names based on personal preferences:

#define NOT(cond) (!(cond))
// or
#define IFN(cond) if (!(cond))
// or
#define IFNOT(cond) if (!(cond))

Therefore, it’s better to address it using a core language feature instead of a macro.

In Ruby, there is an unless statement:

x = 1
unless x > 2
   puts "x lesser than 2"
else
   puts "x greater than 2"
end

In C++, we also have [P1938] elifndef and [P2334] if !consteval :

// P2334 introduced elifndef to C++23
std::size_t my_strlen(char const* str)
{
#ifndef __cpp_lib_freestanding_cstring
    auto end{str};
    for(;*end != '\0'; ++end);
    return static_cast<std::size_t>(end - str);
#else
    return std::strlen(str);
#endif
}

// https://zh.cppreference.com/w/cpp/language/if
constexpr bool is_runtime_evaluated() noexcept
{
    if not consteval { return true; } else { return false; }
}

This pattern is common and easy to understand.

2. Proposal

I propose adding if !(condition) to eliminate redundant parentheses.

Annoying parentheses might deter some developers from using !, even when it makes the logic flow better. Therefore, we can anticipate that the potential usage could exceed its current performance.

Of course, since not is equivalent to ! in C++, this proposal would also allow if not(cond).

Moreover, some might prefer if !(cond) over if (!cond). I think the former, compared to the latter, makes the negation emphasis clearer in certain situations:

// libc++ __tree
if !(__x->__is_black_)
// rather than
if (!__x->__is_black_)
{
    if (__x->__left_ && !__x->__left_->__is_black_)
        return 0;
    if (__x->__right_ && !__x->__right_->__is_black_)
        return 0;
}

3. Syntax

if !opt constexpropt ( init-statementopt condition ) statement
if !opt constexpropt ( init-statementopt condition ) statement else statement

An if statement of the form

if ! constexpropt ( init-statementopt condition ) statement

is equivalent to

if constexpropt ( init-statementopt !(condition) ) statement

and an if statement of the form

if ! constexpropt ( init-statementopt condition ) statement else statement

is equivalent to

if constexpropt ( init-statementopt !(condition) ) statement else statement

4. Impact on existing code

This is a pure extension; it doesn’t affect any existing code.

References

Informative References

[P1938]
Melanie Blower. Add support for preprocessing directives elifdef and elifndef. April 2021. URL: https://wg21.link/p1938
[P2334]
Barry Revzin. if consteval. March 2021. URL: https://wg21.link/p2334