属性 binary_search 的编译错误

Compilation error for a binary_search on the attributes

我有一个向量 v class X

class X
{
public:
  int attribute_1;
  ... 

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

std::vector<X> 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,那么它可以工作,但我想避免这样做(因为 1. 构建 [= 的对象的时间35=] X 它有很多其他属性和 2。我需要编写一个极简主义的构造函数,我害怕我会在代码的其他地方错误地使用它。

我原以为 operator== 重载会使它起作用。为什么它不起作用?有没有一种解决方案不会强迫我用 attribute_1 = elem 创建 X 的实例?

Why does it not work?

std::binary_search 也使用比较对象来检查是否相等。这类似于 comp(a, b) || comp(b, a)。如果该表达式为假,则 a 不小于 b,b 也不小于 a。因此它们必须相等。

由于这种用法,比较对象需要接受集合对象以及要搜索的值作为 第一个和第二个参数。

一种解决方案是使用 "projection" class,其对象既可以根据相关 class 构建,也可以根据您要比较的值构建。在第一种情况下,投影 class 然后从 class 成员中提取值并将其存储到它自己的成员中。在另一种情况下,它只是将值复制到它自己的成员。

有趣的是,这甚至可以变得非常笼统:

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

这个投影class然后作为搜索使用的比较对象的两个参数。 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;
}

上面的代码使用常量成员函数 ("getters"),但它具有以下特殊化 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) {}
};