# std::compare_weak_order_fallback

< cpp‎ | utility

定义于头文件 `<compare>` |  |
inline namespace /* unspecified */ { inline constexpr /* unspecified */ compare_weak_order_fallback = /* unspecified */; } |  | (C++20 起)
调用签名 |  |
template< class T, class U > requires /* see below */ constexpr std::weak_ordering compare_weak_order_fallback(T&& t, U&& u) noexcept(/* see below */); |  |

进行 `t` 与 `u` 上的三路比较并产生 std::weak_ordering 类型结果，即使运算符 `<=>` 不可用。

设 `t` 与 `u` 为表达式而 `T` 与 `U` 分别代表 decltype((t)) 与 decltype((u)) ， std::compare_weak_order_fallback(t, u) 表达式等价于：

- 若 std::is_same_v<std::decay_t<T>, std::decay_t<U>> 为 true ：
  - std::weak_order(t, u) ，若它为良构的表达式；
  - 否则，为

    t == u ? std::weak_ordering::equivalent :
    t < u  ? std::weak_ordering::less :
             std::weak_ordering::greater

    若 t == u 与 t < u 均为良构且可转换到 bool ，除了只求值 `t` 与 `u` 一次。

- 所有其他情况下 std::compare_weak_order_fallback(t, u) 为非良构，这能在出现于模板实例化的立即语境时导致替换失败。

### 表达式等价

表达式 e 表达式等价于表达式 f ，若 e 与 f 拥有相同效果，均为潜在抛出或均非潜在抛出（即 noexcept(e) == noexcept(f) ），且均为常量子表达式或均非常量子表达式。

### 定制点对象

名字 `std::compare_weak_order_fallback` 代表一个定制点对象，它是字面 `semiregular` 类类型的 const 函数对象。为说明目的，以 `__compare_weak_order_fallback_fn` 表示其类型的 cv 无限定版本。

`__compare_weak_order_fallback_fn` 的所有实例均相等。在相同参数上调用类型 `__compare_weak_order_fallback_fn` 的不同实例的效果是等价的，无关乎指代该实例的表达式是左值还是右值，以及是否为 const 限定（然而不要求 volatile 限定的实例可调用）。从而能自由地复制 `std::compare_weak_order_fallback` 并且能彼此替代地使用其副本。

给定类型集合 `Args...` ，若 std::declval<Args>()... 满足上面对于 `std::compare_weak_order_fallback` 的参数要求，则 `__compare_weak_order_fallback_fn` 实现 std::invocable<__compare_weak_order_fallback_fn, Args...>、 std::invocable<const __compare_weak_order_fallback_fn, Args...>、 std::invocable<__compare_weak_order_fallback_fn&, Args...> 及 std::invocable<const __compare_weak_order_fallback_fn&, Args...> 。否则， `__compare_weak_order_fallback_fn` 的函数调用运算符不参与重载决议。

### 示例

    #include <iostream>
    #include <compare>

    // 不支持 <=>
    struct Rational_1 {
        int num;
        int den; // > 0
    };

    inline constexpr bool operator<(Rational_1 lhs, Rational_1 rhs)
    {
        return lhs.num * rhs.den < rhs.num * lhs.den;
    }

    inline constexpr bool operator==(Rational_1 lhs, Rational_1 rhs)
    {
        return lhs.num * rhs.den == rhs.num * lhs.den;
    }

    // 支持 <=>
    struct Rational_2 {
        int num;
        int den; // > 0
    };

    inline constexpr std::weak_ordering operator<=>(Rational_2 lhs, Rational_2 rhs)
    {
        return lhs.num * rhs.den <=> rhs.num * lhs.den;
    }

    void print(std::weak_ordering value)
    {
        if (value == 0)
            std::cout << "equal\n";
        else if (value < 0)
            std::cout << "less\n";
        else
            std::cout << "greater\n";
    }

    int main()
    {
        Rational_1 a{1, 2};
        Rational_1 b{3, 4};
    //  print(a <=> b);                // 不起效
        print(std::compare_weak_order_fallback(a, b)); // 起效，默认到 < 与 ==

        Rational_2 c{6, 5};
        Rational_2 d{8, 7};
        print(c <=> d);                // 起效
        print(std::compare_weak_order_fallback(c, d)); // 起效
    }

输出：

    less
    greater
    greater

### 参阅

weak_order (C++20) | 进行三路比较并产生 `std::weak_ordering` 类型结果 (定制点对象)