[英]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,該操作將在MyType
和Comparable<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.