C++20引入了一个新的比较类型:std::weak_ordering。
它允许表示小于、等于或大于。
然而,一些旧的函数使用int
来实现类似的目的。例如qsort,它使用签名
int compar (const void* p1, const void* p2);
如何将std::weak_ordering
转换为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
}
在测试中,我注意到使用reinterpret_cast
到int8_t
类型确实可以工作,但我不确定这是否是可移植的。
int equivalent_cmp = *(int8_t *)&cmp;
或者等同地,
int equivalent_cmp = *reinterpret_cast<int8_t*>(&cmp);
这样安全吗
此外,还有一些其他的解决方案可以工作,但与这种“不安全”的方法相比效率低下。所有这些都将比上述解决方案慢
int equivalent_cmp = (a > b) - (a < b);
或
int equivalent_cmp;
if (cmp < 0) equivalent_cmp = -1;
else if (cmp == 0) equivalent_cmp = 0;
else equivalent_cmp = 1;
有没有一个更好的解决方案,可以保证工作?
3条答案
按热度按时间b4wnujal1#
有没有一个更好的解决方案,可以保证工作?
没有
该标准没有指定排序类的内容或表示。巴里的答案是基于合理的假设,这些假设可能成立,但不能保证。
如果您需要它,最好的办法是编写类似于上一个代码片段的内容
xa9qqrwz2#
如何将
std::weak_ordering
转换为int
,以便在qsort
这样的函数中使用?简单的答案是:不要使用
qsort
,使用std::sort
,它的性能会更好。也就是说,我们知道
std::weak_ordering
必须有一些整数类型成员,C++20确实有一个机制来提取它:std::bit_cast
:规则是,要转换的类型(在本例中为
int8_t
)必须与要转换的类型(在本例中为std::strong_ordering
)大小相同。这是对bit_cast
的一个约束,所以它是安全的--如果实现实际存储的是int
而不是int8_t
,那么它将无法编译。因此,更一般地说,您必须编写一个简短的元程序来确定要转换为的正确的有符号整数类型。
请注意,虽然
weak_ordering
和strong_ordering
将仅实现为存储整数(尽管不是标准中所示的int
),但partial_ordering
可能 * 不会 * 实现为存储int
和bool
-它可能仍将实现为单个整数。所以这一招行不通。z4iuyo4d3#
我最近需要这个转换,并提出了这个解决方案,如果可能的话,它将使用bit_cast,否则将回落到较慢的方法。