指针值的严格弱排序
Strict weak ordering on pointer values
考虑以下结构:
struct Foo {
const Bar* x;
const Bar* y;
Foo(const Bar* _x, const Bar* _y = nullptr) : x(_x), y(_y) { assert(x); }
}
我们如何在 x 和 y 上定义严格的弱排序,以便对象可以在 std::set 中使用?请注意,y 可以是空指针。正如 中提到的 std::less 对空指针的行为是 undefined 未指定。以下解决方案是否足够?
bool operator<(const Foo& rhs) const {
uintptr_t numX = reinterpret_cast<uintptr_t>(x);
uintptr_t numY = reinterpret_cast<uintptr_t>(y);
uintptr_t numRhsX = reinterpret_cast<uintptr_t>(rhs.x);
uintptr_t numRhsY = reinterpret_cast<uintptr_t>(rhs.y);
return std::tie(numX, numY) < std::tie(numRhsX, numRhsY);
}
编辑:如果不是,正确的方法是什么(例如,如何将 std::less 与 std::tie 结合起来)?
使用 std::less<Bar*>
就足够了(但使用 operator<
就不够了)。 std::less
的指针特化(正如 指出的那样)保证了 总排序 。与 nullptr
的比较是 未指定的,这意味着该标准不强加 特定的 排序,但 std::less
仍必须产生 a 总排序(并且对于给定的指针 p
,p < nullptr
必须每次都产生相同的值)。
由于总排序比弱排序强,因此在您的情况下使用 std::less
就足够了。
EDIT: If not what is the proper way (e.g. how to combine std::less with std::tie)?
不幸的是,没有巧妙的方法。由于 std::tie
returns 和 std::tuple
,并且元组的比较是根据 operator<
对其值(而不是 std::less
)定义的,你不能真的在这里使用 std::tie
。要使用 std::less
,您必须手动执行:
bool operator<(const Foo& rhs) const {
if (std::less<>{}(x, rhs.x))
return true;
if (std::less<>{}(rhs.x, x))
return false;
return std::less<>{}(y, rhs.y);
}
顺便说一句,您当前的实现(将指针重新解释为整数)也产生了总排序(显然,因为您正在比较整数)但是您没有 未指定 行为'将具有 实现定义的 行为(来自 reinterpret_cast
)。
考虑以下结构:
struct Foo {
const Bar* x;
const Bar* y;
Foo(const Bar* _x, const Bar* _y = nullptr) : x(_x), y(_y) { assert(x); }
}
我们如何在 x 和 y 上定义严格的弱排序,以便对象可以在 std::set 中使用?请注意,y 可以是空指针。正如 undefined 未指定。以下解决方案是否足够?
bool operator<(const Foo& rhs) const {
uintptr_t numX = reinterpret_cast<uintptr_t>(x);
uintptr_t numY = reinterpret_cast<uintptr_t>(y);
uintptr_t numRhsX = reinterpret_cast<uintptr_t>(rhs.x);
uintptr_t numRhsY = reinterpret_cast<uintptr_t>(rhs.y);
return std::tie(numX, numY) < std::tie(numRhsX, numRhsY);
}
编辑:如果不是,正确的方法是什么(例如,如何将 std::less 与 std::tie 结合起来)?
使用 std::less<Bar*>
就足够了(但使用 operator<
就不够了)。 std::less
的指针特化(正如 nullptr
的比较是 未指定的,这意味着该标准不强加 特定的 排序,但 std::less
仍必须产生 a 总排序(并且对于给定的指针 p
,p < nullptr
必须每次都产生相同的值)。
由于总排序比弱排序强,因此在您的情况下使用 std::less
就足够了。
EDIT: If not what is the proper way (e.g. how to combine std::less with std::tie)?
不幸的是,没有巧妙的方法。由于 std::tie
returns 和 std::tuple
,并且元组的比较是根据 operator<
对其值(而不是 std::less
)定义的,你不能真的在这里使用 std::tie
。要使用 std::less
,您必须手动执行:
bool operator<(const Foo& rhs) const {
if (std::less<>{}(x, rhs.x))
return true;
if (std::less<>{}(rhs.x, x))
return false;
return std::less<>{}(y, rhs.y);
}
顺便说一句,您当前的实现(将指针重新解释为整数)也产生了总排序(显然,因为您正在比较整数)但是您没有 未指定 行为'将具有 实现定义的 行为(来自 reinterpret_cast
)。