У меня есть объект с функциями для получения начала и конца итераторов:
const_iterator err_begin() const
const_iterator err_end() const
Потому что они не названы begin
а также end
Я не могу передать свой объект напрямую функциям в range-v3.
Есть ли простая оболочка, которую я могу использовать, чтобы этот объект работал с библиотекой range-v3?
Например:
auto hasErrors = !empty(something(x.err_begin(), x.err_end()));
Похоже, вы ищете iterator_range
:
auto hasErrors = !empty(ranges::make_iterator_range(x.err_begin(), x.err_end()));
Вы пояснили, что рассматриваемый класс является частью библиотеки, которую вы не можете изменить. Хорошо. Создайте класс фасада:
class FacadeClass {
const RealClassWithErrBeginEnd &r;
public:
FacadeClass(const RealClassWithErrBeginEnd &r) : r(r) {}
auto begin() const { return r.err_begin(); }
auto end() const { return r.err_end(); }
};
Это должно быть достаточно, чтобы обмануть большую часть кода, который ожидает контейнер. В худшем случае вам может потребоваться предоставить дополнительные определения типов на фасаде, т.е. value_type
, так далее…
boost::make_iterator_range
будет делать правильные вещи. Теперь добавьте немного ADL, и мы обнаружим, что одна бесплатная функция решает все наши проблемы:
#include <vector>
#include <iostream>
#include <string>
#include <boost/range.hpp>// simulate the library class
struct X
{
auto err_begin() const { return errors.begin(); }
auto err_end() const { return errors.end(); }
std::vector<std::string> errors;
};
// provide a generator to build an iterator range
auto errors(const X& x)
{
return boost::make_iterator_range(x.err_begin(), x.err_end());
}
// do things with the iterator_range
int main()
{
X x;
for (const auto& err : errors(x))
{
std::cout << err << std::endl;
}
std::cout << empty(errors(x)) << std::endl;
}