簡體   English   中英

模板類實現比較運算符

[英]Template class implementing comparison operators

將所有重載的比較運算符寫入一個類是我的一項常見任務,因此,我編寫了一個模板類,如果派生類實現了==和<,則該模板類實現<,<=,> =,!=。 它可以正常工作,但是具有很多強制轉換功能,並且沒有明顯的“好奇地重復出現的模板模式”,所以我想知道是否有更簡單的解決方案?

template <class Derived>
class Comparable
{
public:

    bool operator!=(const Comparable<Derived>& other) {
        return !(static_cast<Derived*>(this)->operator==
                     (*static_cast<const Derived*>(&other)));
    }

    bool operator<=(const Comparable<Derived>& other) {
        return (static_cast<Derived*>(this)->operator==
                    (*static_cast<const Derived*>(&other)))
                || (static_cast<Derived*>(this)->operator<
                    (*static_cast<const Derived*>(&other)));
    }

    bool operator>(const Comparable<Derived>& other) {
        return !(static_cast<Derived*>(this)->operator==
                    (*static_cast<const Derived*>(&other)))
                && !(static_cast<Derived*>(this)->operator<
                    (*static_cast<const Derived*>(&other)));
    }

    bool operator>=(const Comparable<Derived>& other) {
        return !(static_cast<Derived*>(this)->operator<
                    (*static_cast<const Derived*>(&other)));
    }
};

如果從注釋中的描述中看不出來:

template <typename T>
struct Comparable {
   friend bool operator!=(T const & lhs, T const & rhs) { return !(lhs == rhs); }
   friend bool operator> (T const & lhs, T const & rhs) { return   rhs <  lhs;  }
// ...
};
class MyType : Comparable<MyType> {
   int data;
   friend bool operator==(MyType const & lhs, MyType const & rhs) {
      return lhs.data == rhs.data;
   }
   friend bool operator< (MyType const & lhs, MyType const & rhs) {
      return lhs.data <  rhs.data;
   }
  public:
// ...
};

當編譯器遇到MyType a, b; a > b; MyType a, b; a > b; 對操作員的查找最終將執行ADL,該操作將在MyTypeComparable<MyType> (因為這是一個基礎)中查找,它將在其中找到所需的實現: bool operator>(MyType const&, MyType const&)

作為自由函數的運算符允許在所比較的類型(在本例中為基數)之外的定義,同時使這些運算符只能通過ADL使用(兩個參數之一必須為Comparable<MyType> )。 使用free函數還提供了類型對稱性,編譯器將允許在兩側進行隱式轉換,而對於成員函數,則僅允許在運算符的右側進行轉換。


為了完整起見,可以采取的另一種技巧是將運算符作為名稱空間中的模板提供,並提供一個標簽,該標簽可用於將其用於ADL用途:

namespace operators {
   template <typename T> 
   bool operator>(T const & lhs, T const & rhs) {
       return rhs < lhs;     
   }
// rest of the operators come here
   struct tag {};
}
class MyType : operators::tag {
   int data;
   friend bool operator<(T const & lhs, T const & rhs) {
      return lhs.data < rhs.data;
   }
//...
};

竅門基本上是相同的,除了在這種情況下,運算符不是在基本內部找到,而是在與之關聯的命名空間中找到。 這種解決方案比以前的解決方案好一點,因為它容易受到多種形式的濫用,包括using namespace operators; 這將使模板化運算符可用於所有類型。

暫無
暫無

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

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