среда, 13 октября 2010 г.

Как подружить BOOST_FOREACH с контейнером без "iterator"

В библиотеке stlsoft есть полезный класс
winstl::findfile_sequence_w, который оборачивает вызовы системных функций FindFirstFileW, FindNextFileW в STL-контейнер. С его помощью перебор файлов реализуется так:
#include <winstl/filesystem/findfile_sequence.hpp>
using namespace stlsoft;
using namespace winstl;

findfile_sequence_w seq(L"c:\", L"*.*", findfile_sequence_w::files); 
findfile_sequence_w::const_iterator p = seq.begin();
while (p != seq.end()) {
   std::wstring filename = (*p).get_filename();
   ++p;
}
Чтобы сделать код более компактным, можно применить BOOST_FOREACH:
findfile_sequence_w seq(L"c:\", L"*.*", findfile_sequence_w::files); 
BOOST_FOREACH(findfile_sequence_w::value_type const& t, f) {
   std::wstring filename = t.get_filename();
}
Но здесь ожидает неприятный сюрприз: BOOST_FOREACH требует наличие двух типов итераторов: iterator и const_iterator. В findfile_sequence_w является псевдо-STL-контейнером - типа "iterator" в нем нет.

Не беда. Функциональность BOOST_FOREACH предусматривает возможность расширения на случай использования нестандартных коллекций.
Так что можно заставить BOOST_FOREACH использовать "const_iterator" вместо "iterator":
#include <boost/foreach.hpp>
namespace boost { 
/*possibility to use BOOST_FOREACH with findfile_sequence_w;
findfile_sequence_w doesn't contain "iterator", it contains only "const_iterator"*/
  template<>
  struct range_mutable_iterator {
      typedef winstl::findfile_sequence_w::const_iterator type;
  };
}
...
BOOST_FOREACH(findfile_sequence_w::value_type const& t, f){}
//or, with same result:
BOOST_FOREACH(findfile_sequence_w::value_type & t, f){}
Поскольку в findfile_sequence_w все функции константные, вреда от такой подмены не будет, а BOOST_FOREACH заработает как надо.

Комментариев нет:

Отправить комментарий