如何将boost :: filter_iterator用作类成员 [英] How to use boost::filter_iterator as a class member
问题描述
大家好,
我正在阅读有关boost的文档 filter_iterator [ ^ ]和我正在尝试按以下方式使用它.
我有两个班级:员工和目录.后者是前者的容器.容器内部使用std :: list来存储数据,因此我可以完全访问std :: list begin()和end()方法.因此,我要公开那些迭代器,而不是列表本身.例如:
Hi everybody,
I''m reading the documentation regarding boost''s filter_iterator[^] and I''m trying to use it as follows.
I have two classes: employee and catalog. The latter is a container for the former. The container, internaly, uses a std::list to store the data and thus I have full access to std::list begin() and end() methods. So, I''m exposing those iterators rather than the list itself. An example:
class employee {
public:
string name;
int age;
};
class catalog
{
public:
typedef list<employee> list_type;
typedef list_type::iterator iterator;
// ...etc...
private:
list_type _list;
public:
iterator begin_all() { return _list.begin(); }
iterator end() { return _list.end(); }
};
我试图以此方式在诸如std :: for_each之类的函数中使用目录.
现在,假设我希望班级过滤那些名称以特定字母开头的员工,或者过滤特定年龄范围内的员工.我期望的公开界面是这样的:
In this manner I''m attempting catalog to be used in functions such as std::for_each.
Now, say that I want the class to filter for those employees whose name starts with a specific letter, or to filter for those within a specific age range. The exposed interface i''m expecting is something like this:
...
public:
iterator begin_age_range(int min, int max) {
// ???
}
现在,我读到Boost的filter_iterator可能可以帮助我解决这一问题.该文档的示例演示了如何在方法中使用它,但是我还没有确定如何使它适应我的需求.
因此,问题是:各位亲爱的CPians,会不会有人就我该如何解决这个问题切掉一个思路,一个线索,一个想法?或者,也许是我以错误的方式来对待它?
¡事先表示感谢!
Now, I have read that Boost''s filter_iterator might be able to help me on this one. The doc''s samples show how to use it within a method, but I haven''t quite determined how to adapt it for my needs.
So, the question is: would any of you, kind CPians, shred a light, a clue, an idea, on how could I solve this problem? Or, perhaps, am I approaching it in a wrong way?
¡Thanks in advance!
推荐答案
您需要创建函子,例如
You need to create a functor, like
struct Range
{
Range(int min, int max): _min(min), _max(max){}
bool operator(int value_)
{
return (_min <= value_ <= _max) ? true : false;
}
int _min;
int _max;
}
现在,从您的类中公开一个新类型(用于增强范围迭代器)
Now expose a new type (for boost range iterator) from your class
....
public:
typedef boost::filter_iterator<range,> FilterIter;
// and these member functions
FilterIter begin_age_range(int min, int max)
{
return boost::make_filter_iterator<range>(Range(min, max), _list.begin(), _list.end());
}
FilterIter begin_age_range(const Range& range)
{
return boost::make_filter_iterator<range>(range, _list.begin(), _list.end());
}
FilterIter end_age_range(int min, int max)
{
return boost::make_filter_iterator<range>(Range(min, max), _list.end(), _list.end());
}
FilterIter end_age_range(const Range& range)
{
return boost::make_filter_iterator<range>(range, _list.end(), _list.end());
}
</range></range></range></range>
您可以像这样使用它-
And you can use it like this-
std::copy(cl.begin_age_range(20, 3000), cl.end_age_range(20, 3000), std::ostream_iterator<int>(std::cout, " "));
</int>
最终您的整个代码看起来像这样-
finally your whole code could look like this-
#include <iostream>
#include <string>
#include <list>
#include <boost/iterator/filter_iterator.hpp>
#include <random>
#include <sstream>
#include <algorithm>
using namespace std;
class employee {
public:
// I added this construtor for ease....
employee(const string& n, const int a): name(n), age(a){}
// I added this for converting into int
operator int() const { return age;}
// I added this to pring employee details
//operator employee() const { cout << "\n Name : " << name << "\t Age : " << age; }
string name;
int age;
};
struct EmployeePrinter
{
EmployeePrinter(){}
void operator()(const employee& emp)
{
cout << "\n Name : " << emp.name << "\t Age : " << emp.age;
}
};
// For Predicate passed to boost
// The Predicate argument must be Assignable, Copy Constructible,
// and the expression p(x) must be valid where p is an object of type Predicate,
// x is an object of type iterator_traits<iterator>::value_type, and where the type of p(x) must be convertible to bool.
struct Range
{
Range(const Range& r): _min(r._min), _max(r._max){}
Range(int min, int max): _min(min), _max(max){}
bool operator()(const employee& emp)
{
return ((_min <= emp.age) && (emp.age <= _max)) ? true : false;
}
int _min;
int _max;
};
class catalog
{
public:
typedef list<employee> list_type;
typedef list_type::iterator iterator;
// ...etc...
typedef boost::filter_iterator<range,> FilterIter;
private:
list_type _list;
public:
iterator begin_all() { return _list.begin(); }
iterator end() { return _list.end(); }
// and these member functions
FilterIter begin_age_range(int min, int max)
{
return boost::make_filter_iterator<range>(Range(min, max), _list.begin(), _list.end());
}
FilterIter begin_age_range(const Range& range)
{
return boost::make_filter_iterator<range>(range, _list.begin(), _list.end());
}
FilterIter end_age_range(int min, int max)
{
return boost::make_filter_iterator<range>(Range(min, max), _list.end(), _list.end());
}
FilterIter end_age_range(const Range& range)
{
return boost::make_filter_iterator<range>(range, _list.end(), _list.end());
}
// I added this function for adding employees...
void add(employee& emp){ _list.push_back(emp);}
};
int main()
{
catalog cl;
for(int i = 0; i < 100; i++)
{
int r = rand();
stringstream ss;
ss << "test_name " << r;
cl.add(employee(ss.str(), r));
}
// now you can use it like this...
std::copy(cl.begin_age_range(20, 3000), cl.end_age_range(20, 3000), std::ostream_iterator<int>(std::cout, " ")); // Int conversiton is used here
std::cout << std::endl;
std::cout << "\n or like this" << std::endl;
// or like this
Range range(5000, 70000);
std::for_each(cl.begin_age_range(range), cl.end_age_range(range), EmployeePrinter());
std::cout << std::endl;
return 0;
}
嗨Ashish,
您的解决方案完美工作,但略有修改.非常感谢您,它确实帮了很多忙.作为记录,我将离开我的工作程序.现在,我将尝试使用std :: function并使用lambdas ... :-)
使其成为单词
Hi Ashish,
Your solution worked perfectly, with a slight modification. Thank you very much, it really helped a lot. For the record, I''ll leave my working program. Now I''ll try to make it word with std::function and using lambdas... :-)
#include <iostream>
#include <string>
#include <list>
#include <functional>
#include <algorithm>
#include
using std::string;
using std::cout;
using std::endl;
using std::list;
using std::function;
using std::for_each;
using std::shared_ptr;
using boost::filter_iterator;
using boost::make_filter_iterator;
class employee;
class employee
{
public:
employee()
: income(0.0), age(0), manager(nullptr)
{ }
employee(const string& name, double income, int age, employee* manager)
: name(name), income(income), age(age), manager(manager)
{ }
employee(const employee& copy)
: name(copy.name), income(copy.income), age(copy.age), manager(copy.manager)
{ }
string manager_name() const {
return manager != nullptr ? manager->name : "[Sin jefe]";
}
void print() const { cout << name << endl; }
string name;
double income;
int age;
employee* manager;
};
struct range_func
{
range_func()
: _min(0), _max(0)
{ }
range_func(const range_func& copy)
: _min(copy._min), _max(copy._max)
{ }
range_func(int min, int max)
: _min(min), _max(max)
{ }
bool operator()(const employee& emp) const {
return _min <= emp.age && emp.age <= _max;
}
int _min;
int _max;
};
struct substr_func
{
substr_func()
{ }
substr_func(const string& str)
: _str(str)
{ }
substr_func(const substr_func& copy)
: _str(copy._str)
{ }
bool operator()(const employee& emp) const {
return emp.name.find(_str) != string::npos;
}
string _str;
};
struct mgr_func
{
mgr_func()
: _ptr(nullptr)
{ }
mgr_func(employee* ptr)
: _ptr(ptr)
{ }
mgr_func(const mgr_func& copy)
: _ptr(copy._ptr)
{ }
bool operator()(const employee& emp) const {
bool val = false;
if (_ptr == nullptr)
val = emp.manager == nullptr;
else
val = emp.manager_name() == _ptr->name;
return val;
}
employee* _ptr;
};
class catalog
{
public:
typedef list<employee> employee_list;
typedef employee_list::size_type size_type;
typedef employee_list::iterator iterator;
typedef employee_list::const_iterator const_iterator;
typedef filter_iterator<range_func,> range_filter_iterator;
typedef filter_iterator<substr_func,> substr_filter_iterator;
typedef filter_iterator<mgr_func,> mgr_filter_iterator;
private:
employee_list _employees;
public:
catalog() { }
size_type size() const { return _employees.size(); }
void clear() { _employees.clear(); }
void add(const employee& emp) { _employees.push_back(emp); }
void add(const string& name, double income, int age, employee* mgr) {
add(employee(name, income, age, mgr));
}
iterator begin_all() { return _employees.begin(); }
iterator end() { return _employees.end(); }
range_filter_iterator begin_age_range(int min, int max) {
return begin_age_range(range_func(min, max));
}
range_filter_iterator begin_age_range(const range_func& func) {
return make_filter_iterator<range_func>(func, _employees.begin(), _employees.end());
}
range_filter_iterator end_age_range(int min, int max) {
return end_age_range(range_func(min, max));
}
range_filter_iterator end_age_range(const range_func& func) {
return make_filter_iterator<range_func>(func, _employees.end(), _employees.end());
}
substr_filter_iterator begin_substr(const string& value) {
return begin_substr(substr_func(value));
}
substr_filter_iterator begin_substr(const substr_func& func) {
return make_filter_iterator(func, _employees.begin(), _employees.end());
}
substr_filter_iterator end_substr(const string& value) {
return end_substr(substr_func(value));
}
substr_filter_iterator end_substr(const substr_func& func) {
return make_filter_iterator(func, _employees.end(), _employees.end());
}
mgr_filter_iterator begin_mgr(employee* mgr) {
return begin_mgr(mgr_func(mgr));
}
mgr_filter_iterator begin_mgr(const mgr_func& func) {
return make_filter_iterator(func, _employees.begin(), _employees.end());
}
mgr_filter_iterator end_mgr(employee* mgr) {
return end_mgr(mgr_func(mgr));
}
mgr_filter_iterator end_mgr(const mgr_func& func) {
return make_filter_iterator(func, _employees.end(), _employees.end());
}
};
int main(int argc, char* argv[])
{
catalog cat;
employee fer("Fernando", 10000, 29, nullptr);
cat.add(fer);
cat.add("Gabriela", 13500, 26, &fer);
employee jime("Jimena", 9500, 22, &fer);
cat.add(jime);
cat.add("Mario", 4300, 37, &jime);
employee caty("Catalina", 15000, 31, nullptr);
cat.add(caty);
employee gis("Gisela", 14750, 30, &caty);
cat.add(gis);
cat.add("Omar", 12700, 30, &gis);
auto func = [](const employee& emp) {
emp.print();
};
cout << "*** Todos los empleados *** " << endl;
for_each(cat.begin_all(), cat.end(), func);
cout << endl;
cout << "***** POR EDAD *****" << endl;
cout << "Edad entre 25 y 30" << endl;
for_each(cat.begin_age_range(25, 30), cat.end_age_range(25, 30), func);
cout << endl;
cout << "Edad menor a 25" << endl;
for_each(cat.begin_age_range(0, 25), cat.end_age_range(0, 25), func);
cout << endl;
cout << "Edad mayor a 30" << endl;
for_each(cat.begin_age_range(30, 100), cat.end_age_range(30, 100), func);
cout << endl;
cout << "***** POR NOMBRE *****" << endl;
cout << "Nombre que contenga 'na'" << endl;
for_each(cat.begin_substr("na"), cat.end_substr("na"), func);
cout << endl;
cout << "Nombre que contenga 'ri'" << endl;
for_each(cat.begin_substr("ri"), cat.end_substr("ri"), func);
cout << endl;
cout << "***** POR JEFE *****" << endl;
cout << "Le reportan a Fernando" << endl;
for_each(cat.begin_mgr(&fer), cat.end_mgr(&fer), func);
cout << endl;
cout << "Le reportan a Caty" << endl;
for_each(cat.begin_mgr(&caty), cat.end_mgr(&caty), func);
cout << endl;
system("pause");
return 0;
}
</range_func></range_func></employee></algorithm></functional></list></string></iostream>
输出为:
The output being:
*** Todos los empleados ***
Fernando
Gabriela
Jimena
Mario
Catalina
Gisela
Omar
***** POR EDAD *****
Edad entre 25 y 30
Fernando
Gabriela
Gisela
Omar
Edad menor a 25
Jimena
Edad mayor a 30
Mario
Catalina
Gisela
Omar
***** POR NOMBRE *****
Nombre que contenga 'na'
Fernando
Jimena
Catalina
Nombre que contenga 'ri'
Gabriela
Mario
***** POR JEFE *****
Le reportan a Fernando
Gabriela
Jimena
Le reportan a Caty
Gisela
Press any key to continue . . .
这篇关于如何将boost :: filter_iterator用作类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!