2013-05-12 38 views
0

我有一套Vec3b來保存可能的RGB像素值。集合的錯誤行爲<Vec3b>

std::set<cv::Vec3b> used_colors; 


但是行爲怪異:

used_colors.insert(cv::Vec3b(100, 255, 255)); 

// this returns 1 although (100, 0, 0) is NOT in the set 
used_colors.count(cv::Vec3b(100, 0, 0)); 


的值(100,0,0)被發現,因爲由100其他值在已經插入集合。其他值(如80,0,0)無法找到。這顯然是錯誤的怪異行爲。


我實現了<對比操作是這樣的:

bool operator <(const cv::Vec3b &a, const cv::Vec3b &b) { 
    if(a[0] < b[0]) 
     return true; 

    if(a[0] > b[0]); 
     return false; 

    if(a[1] < b[1]) 
     return true; 

    if(a[1] > b[1]); 
     return false; 

    if(a[2] < b[2]) 
     return true; 

    if(a[2] > b[2]); 
     return false; 

    return false; 
} 
+1

寫一些測試代碼來獨立運用'operator <'。一旦它正常工作,移動到更復雜的數據結構。這被稱爲「單元測試」,它是創建可靠代碼的基本工具。 – 2013-05-12 10:50:01

回答

4

operator<被打破,由於錯誤的分號後幾個if語句。

考慮輸入a = Vec3b(100, 255, 255)b = Vec3b(100, 0, 0)。因爲兩者的R值是100測試使得它

if(a[0] > b[0]); // <-- notice the semicolon? 

由於該尾隨分號函數無條件返回false。由於相同的原因,比較b < a也返回false;並且set::count認爲該元素已經存在。

擺脫尾隨分號,您的比較運算符按預期工作。


,而無需手動編寫這些比較做lexographical排序,更容易,更不容易出錯的方法是使用std::tie

bool operator<(const cv::Vec3b &a, const cv::Vec3b &b) 
{ 
    return std::tie(a[0], a[1], a[2]) < std::tie(b[0], b[1], b[2]); 
} 
+0

嘎,打我1分鐘。 +1添加關於嚴格弱排序的位。 – Yuushi 2013-05-12 05:10:23

+0

@Yuushi我刪除了關於嚴格弱排序的一點。正如所寫的那樣,比較運算符可能會違反其他一些輸入的嚴格的弱排序,但是對於所示的示例它並不這麼做;所以提到它是一種紅鯡魚。 – Praetorian 2013-05-12 05:13:32

+0

謝謝你們。當你在上午6點編碼時,會發生這種情況。 – 2013-05-12 09:54:08

3

你比較函數釀,可能是因爲你以後有;您的if報表編號。

即便如此,這遠比它需要的複雜。 std::tie使之成爲一行:

bool operator <(const cv::Vec3b &a, const cv::Vec3b &b) 
{ 
    return std::tie(a[0], a[1], a[2]) < std::tie(b[0], b[1], b[2]); 
}