C++ 安全高效地将 std::weak_ordering 转换为 int

The*_*att 3 c++ casting compare c++20

C++20 引入了一种新的比较类型:std::weak_ordering

它允许表示小于、等于或大于。

然而,一些较旧的函数使用 anint来实现类似的目的。例如qsort,它使用签名

int compar (const void* p1, const void* p2);
Run Code Online (Sandbox Code Playgroud)

如何将std::weak_orderingto转换int为在诸如 之类的函数中使用qsort

下面是一个示例情况:

#include <compare>
#include <iostream>

int main() {
    long a = 2354, b = 1234;
    std::weak_ordering cmp = a <=> b;
    
    if (cmp > 0)  std::cout << "a is greater than b" << std::endl;
    if (cmp == 0) std::cout << "a is equal to b" << std::endl;
    if (cmp < 0)  std::cout << "a is less than b" << std::endl;

    int equivalent_cmp = cmp; // errors
}
Run Code Online (Sandbox Code Playgroud)

在测试中,我注意到使用reinterpret_castto int8_ttype 确实有效,但我不确定这是否可以移植。

int equivalent_cmp = *(int8_t *)&cmp;
Run Code Online (Sandbox Code Playgroud)

或同等地,

int equivalent_cmp = *reinterpret_cast<int8_t*>(&cmp);
Run Code Online (Sandbox Code Playgroud)

这安全吗?

此外,还有一些其他解决方案可以工作,但与这种“不安全”的方法相比效率较低。所有这些都会比上述解决方案慢

    int equivalent_cmp = (a > b) - (a < b);
Run Code Online (Sandbox Code Playgroud)

或者

    int equivalent_cmp;
    if (cmp < 0)       equivalent_cmp = -1;
    else if (cmp == 0) equivalent_cmp =  0;
    else               equivalent_cmp =  1;
Run Code Online (Sandbox Code Playgroud)

有没有更好的解决方案可以保证有效?

Jef*_*ett 5

有没有更好的解决方案可以保证有效?

不。

该标准没有指定排序类别的内容或表示。巴里的答案是基于合理的假设,这些假设可能成立,但不能保证。

如果您需要它,最好的选择是编写类似于最后一个片段的内容

constexpr int ordering_as_int(std::weak_ordering cmp) noexcept {
    return (cmp < 0) ? -1 : ((cmp == 0) ? 0 : 1);
}
Run Code Online (Sandbox Code Playgroud)