2010-10-21 73 views
0

我有一個有兩種排序定義的類。 (在真正的問題中,一個是總順序,另一個是半順序。)但是,能夠使用比較運算符而不是總是使用顯式比較函數或函子對象是很好的。所以,我想我會提供一些比較操作是這樣的:詞彙範圍的排序行爲

class C; 

namespace Order1 { 
    bool operator< (const C&, const C&); 
} 
namespace Order2 { 
    bool operator< (const C&, const C&); 
} 

運營商爲><=>=也被定義,當然,不過這不是重點。現在,用戶可以在文件範圍或塊範圍內說using namespace Order1;或... Order2,並獲取該文件/塊的其餘部分的請求行爲。

令人失望的部分,我想盡可能提高,這些using s不能嵌套。在同一個命名空間中使用時

void g(const C&, const C&); 

using namespace Order1; // for most functions in this file 

void f(const C& x, const C& y) { 
    bool test1 = x < y; // Order1 
    { 
    // Would like to switch to Order2 for this block. 
    using namespace Order2; 
    bool test2 = x < y; // Ambiguous overload! 

    g(x, y); // Unaffected by local using-s. 
    } 
} 

由於using -directives不隱瞞任何東西,這並沒有提供一種方式來很好地暫時扭轉操作符的含義爲塊範圍。

另一個相關的想法是允許堆棧上的構造函數和析構函數操作「當前設置」的虛擬對象,以便使用該行爲。但我不認爲我想以這種方式來處理這種情況,因爲這意味着相當於上面的f可能會改變稱爲g等其他函數的行爲。

是否有另一種方式獲得類似的效果,但允許嵌套操作與最內層的塊「隱藏」其他?或者我堅持每個聲明區域的重載操作符的行爲?我認爲這是可以管理的,因爲代碼仍然可以明確地使用函數或仿函數而不是使用操作符。

+3

顯式是好的,隱式是壞的。大致。恕我直言。 :-)乾杯, – 2010-10-21 14:48:17

+0

我沒有提到的一件事是,這是一個已有的類已經有這些運營商,併成千上萬的文件使用的變化。所以我堅持提供一個「默認」操作符行爲,這大部分都是舊行爲。但我想我會推薦使用顯式函數或函子的新代碼,而不是與操作符混淆。我只希望有些同事能聽取建議。 – aschepler 2010-10-21 15:21:46

回答

2

我會堅持普通的比較功能。其餘代碼將更清潔。否using namespace...或明確調用範圍operator<。通過這種方式讀取更容易,IMO ...

int main() { 
    bool b = compare1(4, 5); 
    b = compare2(4, 5); 
} 
0

,而不是使用命名空間Order2放在

bool test2 = Order2::operator<(x, y); 

將在這種情況下工作。如果你想要「元程序」,即能夠傳遞Order1/Order2作爲模板參數,你應該使它們成爲靜態的運算符(或類),其運算符爲<。那麼你可以做T :: operator <(x,y),其中T是Order1或Order2。

+0

如果需要一個更具體的語法,我寧願用'Order2 :: compare(x,y)<0',或者繼承'std :: binary_function'的函子'Order2 :: Comp()' '。我想我只是爲了自己的利益而過於懶惰。 – aschepler 2010-10-21 15:02:37

+0

如果你使用一個類,你可以重載operator()。您需要創建該類的「虛擬」實例。然後你使用compareObj(x,y)。 – CashCow 2010-10-22 11:14:10

0

爲什麼不廢棄命名空間,只聲明兩個重載operator <具有不同的參數類型,每個類類型一個?

UPDATE

由於dgnorton指出在下面評論,你有一類,與上定義了兩個不同的排序。這確實看起來像是問題的可能原因。是否可以將它分成兩個不同的類?

+0

在他的情況下,類的類型是相同的...他希望同一個操作符的不同行爲......這可能不是一個好主意。 – dgnorton 2010-10-21 14:56:01

+0

如果他打算將謂詞傳遞給一個算法或一個std :: set或類似的命令來給出不同的排序,這可能是一個好主意。如果他將地圖放入每個名稱空間,它可能會自動從該名稱空間中拾取運算符,儘管Koenig Lookup表明它可能會首先查找該類的名稱空間。 – CashCow 2010-10-22 08:39:12