boost содержит удобную обертку
indirect_iterator. Эта обертка делает дополнительное разыменование в
operator*(). Это позволяет удобно работать с контейнерами, которые содержат указатели на элементы вместо самих элементов. Например,
struct test {
int field1;
test( int v ) : field1( v ) {}
};
typedef boost::shared_ptr<test> test_ptr_t;
typedef std::vector<test_ptr_t> test_t;
test_t test_array;
int main()
{
test_array.push_back( test_ptr_t( new test(1) ) );
test_array.push_back( test_ptr_t( new test(5) ) );
test_array.push_back( test_ptr_t( new test(10) ) );
typedef boost::indirect_iterator<test_t::const_iterator> test_const_iterator;
using boost::make_indirect_iterator;
for ( test_const_iterator it = make_indirect_iterator( test_array.begin() );
it != make_indirect_iterator( test_array.end() ); ++it )
{
// пишем it->field1 вместо (*it)->field1
std::cout << it->field1 << std::endl;
}
}
Писанины многовато, но иногда оно того стоит. В алгоритамах
indirect_iterator упрощает написание функторов:
test_const_iterator f = std::find_if(
make_indirect_iterator( test_array.begin() ),
make_indirect_iterator( test_array.end() ),
boost::bind( &test::field1, _1 ) == 5 );
std::cout << f->field1 << std::endl;
Стоит отметить, что счастливые пользователи компиляторов с поддержкой нового стандарта(например, GNU C++ 4.5 или MSVC++ 2010) могут заменить все это ситаксическое безобразие лямбда функциями и написать следующее:
auto x = std::find_if(
test_array.begin(),
test_array.end(),
[](test_ptr_t v) { return v->field1 == 5; } );
std::cout << (*x)->field1 << std::endl;