簡體   English   中英

指針值的嚴格弱排序

[英]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和nullptr中所提到的,未指定 未定義 std :: less on null指針的行為。 以下解決方案是否足夠?

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的指針特化(作為“使用std :: less with nullptr”的接受答案指出)保證了總排序 與比較nullptr不確定的 ,這意味着該標准沒有強加特定排序,但std::less仍然必須產生總體排序(以及對於給定的指針pp < nullptr必然產生相同的值每次)。

由於總排序強於弱排序,因此在您的情況下使用std::less就足夠了。

編輯:如果不是正確的方法(例如如何將std :: less與std :: tie結合起來)?

不幸的是,沒有簡潔的方法。 由於std::tie返回一個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 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM