brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.6 KiB · bd31388 Raw
255 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// <compare>12 13// template<class T> constexpr partial_ordering partial_order(const T& a, const T& b);14 15#include <compare>16 17#include <cassert>18#include <cmath>19#include <iterator> // std::size20#include <limits>21#include <type_traits>22#include <utility>23 24#include "test_macros.h"25 26template<class T, class U>27constexpr auto has_partial_order(T&& t, U&& u)28    -> decltype(std::partial_order(static_cast<T&&>(t), static_cast<U&&>(u)), true)29{30    return true;31}32 33constexpr bool has_partial_order(...) {34    return false;35}36 37namespace N11 {38    struct A {};39    struct B {};40    std::strong_ordering partial_order(const A&, const A&) { return std::strong_ordering::less; }41    std::strong_ordering partial_order(const A&, const B&);42}43 44void test_1_1()45{46    // If the decayed types of E and F differ, partial_order(E, F) is ill-formed.47 48    static_assert( has_partial_order(1, 2));49    static_assert(!has_partial_order(1, (short)2));50    static_assert(!has_partial_order(1, 2.0));51    static_assert(!has_partial_order(1.0f, 2.0));52 53    static_assert( has_partial_order((int*)nullptr, (int*)nullptr));54    static_assert(!has_partial_order((int*)nullptr, (const int*)nullptr));55    static_assert(!has_partial_order((const int*)nullptr, (int*)nullptr));56    static_assert( has_partial_order((const int*)nullptr, (const int*)nullptr));57 58    N11::A a;59    N11::B b;60    static_assert( has_partial_order(a, a));61    static_assert(!has_partial_order(a, b));62}63 64namespace N12 {65    struct A {};66    std::strong_ordering partial_order(A&, A&&) { return std::strong_ordering::less; }67    std::weak_ordering partial_order(A&&, A&&) { return std::weak_ordering::equivalent; }68    std::strong_ordering partial_order(const A&, const A&);69 70    struct B {71        friend int partial_order(B, B);72    };73 74    struct PartialOrder {75        explicit operator std::partial_ordering() const { return std::partial_ordering::less; }76    };77    struct C {78        bool touched = false;79        friend PartialOrder partial_order(C& lhs, C&) { lhs.touched = true; return PartialOrder(); }80    };81}82 83void test_1_2()84{85    // Otherwise, partial_ordering(partial_order(E, F))86    // if it is a well-formed expression with overload resolution performed87    // in a context that does not include a declaration of std::partial_order.88 89    // Test that partial_order does not const-qualify the forwarded arguments.90    N12::A a;91    assert(std::partial_order(a, std::move(a)) == std::partial_ordering::less);92    assert(std::partial_order(std::move(a), std::move(a)) == std::partial_ordering::equivalent);93 94    // The type of partial_order(e,f) must be explicitly convertible to partial_ordering.95    N12::B b;96    static_assert(!has_partial_order(b, b));97 98    N12::C c1, c2;99    ASSERT_SAME_TYPE(decltype(std::partial_order(c1, c2)), std::partial_ordering);100    assert(std::partial_order(c1, c2) == std::partial_ordering::less);101    assert(c1.touched);102    assert(!c2.touched);103}104 105namespace N13 {106    // Compare to N12::A.107    struct A {};108    bool operator==(const A&, const A&);109    constexpr std::partial_ordering operator<=>(A&, A&&) { return std::partial_ordering::less; }110    constexpr std::partial_ordering operator<=>(A&&, A&&) { return std::partial_ordering::equivalent; }111    std::partial_ordering operator<=>(const A&, const A&);112    static_assert(std::three_way_comparable<A>);113 114    struct B {115        std::partial_ordering operator<=>(const B&) const;  // lacks operator==116    };117    static_assert(!std::three_way_comparable<B>);118 119    struct C {120        bool *touched;121        bool operator==(const C&) const;122        constexpr std::partial_ordering operator<=>(const C& rhs) const {123            *rhs.touched = true;124            return std::partial_ordering::equivalent;125        }126    };127    static_assert(std::three_way_comparable<C>);128}129 130constexpr bool test_1_3()131{132    // Otherwise, partial_ordering(compare_three_way()(E, F)) if it is a well-formed expression.133 134    // Test neither partial_order nor compare_three_way const-qualify the forwarded arguments.135    N13::A a;136    assert(std::partial_order(a, std::move(a)) == std::partial_ordering::less);137    assert(std::partial_order(std::move(a), std::move(a)) == std::partial_ordering::equivalent);138 139    N13::B b;140    static_assert(!has_partial_order(b, b));141 142    // Test that the arguments are passed to <=> in the correct order.143    bool c1_touched = false;144    bool c2_touched = false;145    N13::C c1 = {&c1_touched};146    N13::C c2 = {&c2_touched};147    assert(std::partial_order(c1, c2) == std::partial_ordering::equivalent);148    assert(!c1_touched);149    assert(c2_touched);150 151    // For partial_order, this bullet point takes care of floating-point types;152    // they receive their natural partial order.153    {154        using F = float;155        F nan = std::numeric_limits<F>::quiet_NaN();156        assert(std::partial_order(F(1), F(2)) == std::partial_ordering::less);157        assert(std::partial_order(F(0), -F(0)) == std::partial_ordering::equivalent);158#ifndef TEST_COMPILER_GCC  // GCC can't compare NaN to non-NaN in a constant-expression159        assert(std::partial_order(nan, F(1)) == std::partial_ordering::unordered);160#endif161        assert(std::partial_order(nan, nan) == std::partial_ordering::unordered);162    }163    {164        using F = double;165        F nan = std::numeric_limits<F>::quiet_NaN();166        assert(std::partial_order(F(1), F(2)) == std::partial_ordering::less);167        assert(std::partial_order(F(0), -F(0)) == std::partial_ordering::equivalent);168#ifndef TEST_COMPILER_GCC169        assert(std::partial_order(nan, F(1)) == std::partial_ordering::unordered);170#endif171        assert(std::partial_order(nan, nan) == std::partial_ordering::unordered);172    }173    {174        using F = long double;175        F nan = std::numeric_limits<F>::quiet_NaN();176        assert(std::partial_order(F(1), F(2)) == std::partial_ordering::less);177        assert(std::partial_order(F(0), -F(0)) == std::partial_ordering::equivalent);178#ifndef TEST_COMPILER_GCC179        assert(std::partial_order(nan, F(1)) == std::partial_ordering::unordered);180#endif181        assert(std::partial_order(nan, nan) == std::partial_ordering::unordered);182    }183 184    return true;185}186 187namespace N14 {188    struct A {};189    constexpr std::strong_ordering weak_order(A&, A&&) { return std::strong_ordering::less; }190    constexpr std::strong_ordering weak_order(A&&, A&&) { return std::strong_ordering::equal; }191    std::strong_ordering weak_order(const A&, const A&);192 193    struct B {194        friend std::partial_ordering weak_order(B, B);195    };196 197    struct StrongOrder {198        operator std::strong_ordering() const { return std::strong_ordering::less; }199    };200    struct C {201        friend StrongOrder weak_order(C& lhs, C&);202    };203 204    struct WeakOrder {205        constexpr explicit operator std::weak_ordering() const { return std::weak_ordering::less; }206        operator std::partial_ordering() const = delete;207    };208    struct D {209        bool touched = false;210        friend constexpr WeakOrder weak_order(D& lhs, D&) { lhs.touched = true; return WeakOrder(); }211    };212}213 214constexpr bool test_1_4()215{216    // Otherwise, partial_ordering(weak_order(E, F)) [that is, std::weak_order]217    // if it is a well-formed expression.218 219    // Test that partial_order and weak_order do not const-qualify the forwarded arguments.220    N14::A a;221    assert(std::partial_order(a, std::move(a)) == std::partial_ordering::less);222    assert(std::partial_order(std::move(a), std::move(a)) == std::partial_ordering::equivalent);223 224    // The type of ADL weak_order(e,f) must be explicitly convertible to weak_ordering225    // (not just to partial_ordering), or else std::weak_order(e,f) won't exist.226    N14::B b;227    static_assert(!has_partial_order(b, b));228 229    // The type of ADL weak_order(e,f) must be explicitly convertible to weak_ordering230    // (not just to strong_ordering), or else std::weak_order(e,f) won't exist.231    N14::C c;232    static_assert(!has_partial_order(c, c));233 234    N14::D d1, d2;235    ASSERT_SAME_TYPE(decltype(std::partial_order(d1, d2)), std::partial_ordering);236    assert(std::partial_order(d1, d2) == std::partial_ordering::less);237    assert(d1.touched);238    assert(!d2.touched);239 240    return true;241}242 243int main(int, char**)244{245    test_1_1();246    test_1_2();247    test_1_3();248    test_1_4();249 250    static_assert(test_1_3());251    static_assert(test_1_4());252 253    return 0;254}255