2017-03-05 11 views
1

私は、クラスのインスタンスXコンパイルエラー

class X 
{ 
public: 
    int attribute_1; 
    ... 

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

std::vector<X> v; 

のベクトルvをベクトルvは属性attribute_1でソートされています。私は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に設定した場合は動作しますが、これは避けたいと思います(クラスXのオブジェクトを作成する時間が1で、他の属性が2つあります。最小限のコンストラクタを書く必要があり、誤ってコード内の別の場所で使用するのは怖いです)。

私はoperator==オーバーロードが動作すると予想しました。なぜそれは機能しませんか? attribute_1 = elemXのインスタンスを作成するような解決策はありませんか?

+0

あなたは、ラムダを使用することはできません。 'operator()'の2つのオーバーロードを持つクラスが必要です。一つは 'X'と' int'を取り、もう一つは 'int'と' X'を取る必要があります。 'elem'と実際のベクトル要素を両方向で比較できるようにする必要があります。あるいは、 'attribute_1'を' elem'に設定した 'X'のインスタンスを構築し、' std :: binary_search'に渡してください。 –

+0

なぜ 'operator =='が何をするのかは不明です。誰がそれを使用するのですか?どのように役立つと期待されていますか?とにかく、実際には 'std :: binary_search'では使われていません。 –

答えて

1

なぜ機能しないのですか?

std::binary_searchは、比較オブジェクトを使用して同等性をチェックします。これはcomp(a, b) || comp(b, a)と同様に行われます。その式が偽であれば、aはbより小さくなく、bはaより小さい。したがって、彼らは平等でなければならない。

このため、比較オブジェクトはコレクションのオブジェクトと、と検索する値を両方とも受け入れる必要があります。第1パラメータと第2パラメータ。

解決策の1つは、対象のクラスと比較する値の両方からオブジェクトを構築できる「投影」クラスを使用することです。最初のケースでは、投影クラスはクラスメンバーから値を抽出し、そのメンバーに値を格納します。それ以外の場合は、値を自分のメンバーにコピーするだけです。

十分に面白い、これもかなり一般的にすることができる。

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) {} 
};