lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi] Shouldn't std::max() and std::min() be commutative?


From: Greg Chicares
Subject: [lmi] Shouldn't std::max() and std::min() be commutative?
Date: Sat, 27 Feb 2021 13:13:47 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0

Surely it is possible to implement std::max() and std::min() as
commutative operations [below], so I wondered whether it is not
therefore at least a QoI issue that libstdc++
  $g++ --version
  g++ (Debian 10.2.1-6) 10.2.1 20210110
does not. The answer is that libstdc++ follows the standard, e.g.,
C++20 (n4861) [alg.min.max / 3]:
  "Remarks: Returns the first argument when the arguments are equivalent."
Is it not therefore a defect of the standard that it prescribes the
jarring and unnecessary behavior demonstrated below? What might they
have been thinking--that a commutative implementation such as this
quick sketch for type double:

    #include <cmath>

    constexpr bool operator()(T const& lhs, T const& rhs) const
    {
        if(0.0 == lhs && 0.0 == rhs)
            {
            return std::signbit(rhs) < std::signbit(lhs);
            }
        else
            {
            return lhs < rhs;
            }
    }

would be too slow?

Or is there some deeper reason--e.g., that using a weak order
everywhere in the standard is more important than commutativity here?

Demonstration:

#include <algorithm>
#include <cfloat>

int main()
{
    std::cout << std::max( 0.0, -0.0) << std::endl; // prints 0
    std::cout << std::min( 0.0, -0.0) << std::endl; // prints 0
    std::cout << std::max(-0.0,  0.0) << std::endl; // prints -0
    std::cout << std::min(-0.0,  0.0) << std::endl; // prints -0

    double n = DBL_TRUE_MIN;
    double a =  0.1 * n;
    double b = -0.1 * n;
    std::cout << a << std::endl; // prints 0
    std::cout << b << std::endl; // prints -0
    std::cout << std::max(a, b) << std::endl; // prints 0
    std::cout << std::min(a, b) << std::endl; // prints 0
    std::cout << std::max(b, a) << std::endl; // prints -0
    std::cout << std::min(b, a) << std::endl; // prints -0

    return 0;
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]