2017-03-05 97 views
1

我有類X對屬性的binary_search編譯錯誤

class X 
{ 
public: 
    int attribute_1; 
    ... 

    operator==(const int i){return this->attribute_1 == i;} 
}; 

std::vector<X> v; 

載體v由屬性attribute_1排序實例的矢量v。我想執行binary_search來測試給定的整數是否與X的其中一個實例的attribute_1匹配。我試過

int elem = 12 
bool isElementPresent = std::binary_search(
     v.begin(), 
     v.end(), 
     elem, 
     [](const X& right, const X& left){return right.attribute_1 < left.attribute_1;} 
    ) 
    ) 

但是無法編譯。如果我創建了X的實例attribute_1設置爲elem,那麼它的工作原理,但我想避免這樣做(因爲1.建立類別爲X的對象有很多其他屬性和2.我會需要編寫一個簡約的構造函數,並且害怕我會在代碼中的其他地方錯誤地使用它)。

我本來預計operator==重載會使它工作。爲什麼它不起作用?有沒有一種解決方案不會強迫我用attribute_1 = elem創建X的實例?

+0

不能使用lambda。你需要一個有兩個'operator()'重載的類,一個取'X'和'int',另一個取'int'和'X'。你需要能夠在兩個方向上比較'elem'和實際的向量元素。或者,構造'attribute'設置爲'elem'的'X'實例,並將其傳遞給'std :: binary_search'。 –

+0

目前還不清楚爲什麼您期望'operator =='有所作爲。誰應該使用它,以及如何?它有什麼幫助?無論如何,它實際上並沒有被'std :: binary_search'使用。 –

回答

1

爲什麼不起作用?

std::binary_search使用比較對象也檢查是否相等。這與comp(a, b) || comp(b, a)類似。如果這個表達式是錯誤的,那麼a不小於b也不小於a。因此他們必須是平等的。

由於這種用法,比較對象需要接受集合的對象以及要搜索的值均爲第一個和第二個參數。

一種解決方案是使用「投影」類,其對象既可以從相關類中構建,也可以從要比較的值中構建。在第一種情況下,投影類然後從類成員中提取值並將其存儲到其自己的成員中。在另一種情況下,它只是將該值複製到其自己的成員。

有趣的是,這甚至可以製成相當普遍的:然後

template<typename D, typename P, P> struct projection; 

template<typename Data, typename Class, typename Return, Return (Class::*member_function)() const> 
struct projection<Data, Return (Class::*)() const, member_function> { 
Data data; 
projection (Class const & object) 
    : data ((object.*member_function)()) {} 
/* template<typename X> 
projection (X&& input) 
    : data (std::forward<X>(input)) {}*/ 
projection (Data d) : data (d) {} 
}; 

該投影類被用作由所述搜索中使用的比較對象的兩個參數。 Example

struct Item { 
int x; 
int get() const { return x; } 
}; 


int main() { 
Item items [] = {1,2,3,4,5,99}; 
using P = projection<int, decltype(&Item::get), &Item::get>; 
auto compare = [](P const & left, P const & right) { 
       return left.data < right.data; }; 
std::cout << std::binary_search(
     std:: begin (items), std::end(items), 
     4, compare) 
    << std::endl; 
std::cout << std::binary_search(
     std:: begin (items), std::end(items), 
     44, compare) 
    << std::endl; 
} 

上面的代碼使用常量成員函數( 「干將」),但具有下列專業化它also works with pointers to members

template<typename Data, typename Class, typename Member, Member (Class::*member_pointer)> 
struct projection<Data, Member (Class::*), member_pointer> { 
Data data; 
projection (Class const & object) 
    : data (object.*member_pointer) {} 
/* template<typename X> 
projection (X&& input) 
    : data (std::forward<X>(input)) {}*/ 
projection (Data d) : data (d) {} 
};