Skip to content

71 Advanced The Hundred

&& Without the Shortcut

two ampersands, zero protection

#include <iostream>

struct Check {
    bool ok;
    const char* msg;
};

Check operator&&(Check a, Check b) { return a.ok ? b : a; }

Check user_exists() {
    std::cout << "looking up user... not found\n";
    return {false, "no such user"};
}

Check charge_card() {
    std::cout << "charging card!\n";
    return {true, "payment accepted"};
}

int main() {
    Check result = user_exists() && charge_card();
    std::cout << "result: " << result.msg << "\n";
}

Run it. Does the card get charged?

Answer

Yes. charging card! prints even though the lookup failed — yet the result still says no such user.

Why

Built-in && short-circuits: the right side runs only when the left is true — the whole reason ptr && ptr->next is safe. An overloaded && is an ordinary function call: user_exists() && charge_card() means operator&&(user_exists(), charge_card()), and a function needs both arguments evaluated before it can be called. No overload body, however clever, can peek at the left value and skip the right — skipping would have to happen at the call site, and call sites don't skip arguments. C++17 fixed the ordering (the left operand is now evaluated first; before that it was unspecified), but that is all it fixed — short-circuiting is never restored. operator|| loses short-circuiting the same way; the overloaded comma lost its sequencing too, until C++17 restored it. -Wall -Wextra stays silent: this is perfectly legal C++, just perfectly misleading.

The fix

Don't overload &&, ||, or the comma. If you want a chaining combinator, take the right-hand side as a callable, so it only runs on demand:

template <class F>
Check and_then(Check a, F next) { return a.ok ? next() : a; }

Check result = and_then(user_exists(), charge_card);   // no () — the card is safe

Takeaway: overloading && keeps the spelling but trades away short-circuiting — its defining feature — so don't.

Try it: g++ -std=c++17 main.cpp -o demo && ./demo

Open in Compiler Explorer ↗ Quiz this entry