簡體   English   中英

三向比較運算符成員與非成員實現

[英]Three-way comparison operator member vs non-member implementation

在以下情況下,雙向比較運算符應為非成員函數:

  • 您希望第一個操作數的類型不是此類
  • 您想要兩個操作數中的任何一個進行隱式類型轉換

新的C ++ 20三向比較運算符具有對稱的生成規則。 表達式a@b的名稱查找(其中@是一種雙向比較運算符)以a@ba<=>bb<=>a順序進行(在模棱兩可的情況下,此優先順序為從過載分辨率設置中選擇最佳匹配時)。 有關詳細信息,請參見P0515R2 這意味着運算符<=>可以是成員函數,並且仍然允許第一個操作數不屬於此類。

但是,該文件包含以下注釋:

通常,operator <=>應該只是成員函數。 由於§2.3中的對稱生成規則,您仍將獲得每個參數的轉換。 在極少數情況下,您還希望同時支持兩個參數的轉換(要啟用兩個都不屬於此類型的對象的比較,而是要使用此類型的比較功能),請使其成為非成員朋友。

如果我正確理解這一點,它說僅當需要同時對兩個操作數進行隱式轉換時才需要非成員實現嗎? 那是對的嗎? 我可以在需要時看到一個實際示例嗎? 我正在考慮這一點,盡管它似乎不是一個有效的示例:

struct foo
{
   foo(int const x) 
      : data{ x } {}
   foo(std::string_view x) 
      : data{std::stoi(x.data())}{}

   friend auto operator<=>(foo const & lhv, foo const & rhv) noexcept
   {
      return lhv.data <=> rhv.data;
   }

private:
   int data;
};


int main()
{
   assert(foo {42} == foo {"42"});        // OK
   assert(42 == std::string_view("42"));  // ??
}

這是一個說明性(盡管不一定實際)示例:

struct A {
    int i;
};

struct B {
    B(A a) : i(a.i) { }

    int i;
};

strong_ordering operator<=>(B const& lhs, B const& rhs) {
    return lhs.i <=> rhs.i;
}

A{2} == A{2}; // okay, true
A{2} < A{1};  // okay, false

我們發現候選者在全局范圍內取兩個B ,並且它是可行的,因此我們將兩個參數都轉換並使用它。 如果該運算符是在類中聲明的成員函數或非成員friend ,則名稱查找將找不到它。


請注意,在OP中, <=>被聲明為該類中的非成員friend 這意味着對於42 == string_view("42") ,名稱查找將找不到它,因為這些參數都不是foo 您將需要添加一個普通的非成員聲明,​​以使其對於此類查找可見。

暫無
暫無

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

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