How can I search a container of objects for a data member value?

浪尽此生 提交于 2020-01-13 17:03:10

问题


I have an object type like this:

struct T
{
   int x;
   bool y;
};

and a container of them like this:

std::vector<T> v;

and a burning desire to determine — in a single statement — whether any of the elements of v have y == true. This likely involves std::find_if.

My understanding is that std::bind and boost::bind are for member functions and cannot be applied to member data.


Because I dislike them, I wish to avoid:

  • comparison functions/functors
  • loops

Because my environment is C++03, the following are not available:

  • lambdas

回答1:


My understanding is that std::bind and boost::bind are for member functions and cannot be applied to member data.

Remarkably, this is not the case! boost::bind will happily bind to member data and allow you to perform operations on it during an "inline iteration".

From the documentation:

Pointers to member functions and pointers to data members are not function objects, because they do not support operator(). For convenience, bind accepts member pointers as its first argument, and the behavior is as if boost::mem_fn has been used to convert the member pointer into a function object. In other words, the expression

bind(&X::f, args)

is equivalent to

bind<R>(mem_fn(&X::f), args)

where R is the return type of X::f (for member functions) or the type of the member (for data members.)

Also, from the documentation for boost::mem_fn:

mem_fn also supports pointers to data members by treating them as functions taking no arguments and returning a (const) reference to the member.

So, you can do this:

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <boost/bind.hpp>

struct T
{
   int x;
   bool y;
};

void f(const std::string& name, const std::vector<T>& v)
{
   const bool found = std::find_if(
      v.begin(),
      v.end(),
      boost::bind(&T::y, _1) == true
   ) != v.end();

   std::cout << name << ": " << (found ? " FOUND" : " not found") << '\n';
}

int main()
{
   T a = { 0, false };
   T b = { 1, false };
   T c = { 2, true  };

   std::vector<T> v;
   f("a", v);

   v.push_back(a);
   v.push_back(b);
   f("b", v);

   v.push_back(c);
   f("c", v);
}

Output:

a: not found
b: not found
c: FOUND




回答2:


What you want (to determine — in a single statement — whether any of the elements of v have y == true) seems to be:

inline bool y_is_true(std::vector<T>::iterator i) { return i->y; };

(outside your function) and

bool found = std::find_if(v.begin(), v.end(), y_is_true) != v.end();

Another option is to use boost::lambda:

bool found = std::find_if(v.begin(), v.end(), _1.y) != v.end();


来源:https://stackoverflow.com/questions/17196690/how-can-i-search-a-container-of-objects-for-a-data-member-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!