C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Using -1 as the max value for an unsigned integer

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Fri, 18 Jul 2025 15:56:59 +0100
On Friday, July 18, 2025, David Brown wrote:


> Finally, I suggest you stop writing nonsense in your code. A TCP/IP port
> is a number between 1 and 65535 (UDP allows port 0 in some circumstances to
> mean "no port"). If you have a number and you want to check its validity
> as a port number, check it against these two values - 1 and 65535 (or
> 0xffff if you prefer hex, or define an identifier for it if you think it
> makes the code clearer). Using "-1" as a maximum value for an unsigned
> type is nonsense.




I have a trick I do with unsigned numbers in multi-threaded programs.

I define the variable, maybe something like:

    std::atomic< std::size_t > n{0u};

0 is an invalid number.

The first threads starts the second thread. The second thread assigns to
'n'. If the second thread fails, 'n' remains as zero... but that's a
problem if the first thread does this:

    n.wait(0u);

Therefore in the second thread, I set 'n' to its max value upon failure so
that the first thread will unblock.

So when I'm dealing with an unsigned integer variable shared between
multiple threads, I blacklist 0 and its max value as invalid, like this:

    if ( 0u==n || -1==n ) . . .

But from now on I'll write:

    if ( 0u==n || _Max==n ) . . .

Of course I could instead use a second variable, maybe a semaphore or a
condition variable or an atomic boolean, but I like my strategy, which can
be summed up as: "If all the bits are the same, it's invalid".

I've already committed the new header file '_Max.hpp' to my project and
eradicated uses of -1 for unsigned types:

#ifndef HEADER_INCLUSION_GUARD_fbde6307_28ac_4082_904d_2984d8802179
#define HEADER_INCLUSION_GUARD_fbde6307_28ac_4082_904d_2984d8802179

#include <limits> // numeric_limits<T>::max()
#include <type_traits> // is_integral, is_unsigned

struct _Max_t {
    template<typename T> requires std::is_integral_v<T> &&
std::is_unsigned_v<T>
    constexpr operator T(void) const
    {
        // Some compilers define 'max' as a preprocessor macro
        // function, so we use a function pointer here.
        constexpr auto FuncPtr = &std::numeric_limits<T>::max;
        return FuncPtr();
    }
    template<typename T> requires std::is_integral_v<T> &&
std::is_unsigned_v<T>
    constexpr bool operator==(T const n) const
    {
        // Some compilers define 'max' as a preprocessor macro
        // function, so we use a function pointer here.
        constexpr auto FuncPtr = &std::numeric_limits<T>::max;
        return n == FuncPtr();
    }
};

constexpr _Max_t _Max{};

#endif

Received on 2025-07-18 14:57:02