如何将boost :: filter_iterator用作类成员 [英] How to use boost::filter_iterator as a class member

查看:95
本文介绍了如何将boost :: filter_iterator用作类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,

我正在阅读有关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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆