如何从开始和结束迭代器创建范围?

问题描述 投票:0回答:3

我有一个带有用于获取开始和结束迭代器的函数的对象:

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())); 
c++ range-v3
3个回答
19
投票

如果您仍在使用 range-v3,您会需要

iterator_range
:

auto hasErrors = !empty(ranges::make_iterator_range(x.err_begin(), x.err_end()));

对于 C++20 及以上版本,您可以使用

subrange
:

auto hasErrors = !empty(std::ranges::subrange{x.err_begin(), x.err_end()});

4
投票

您澄清了相关类是您无法更改的库的一部分。美好的。创建门面类:

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(); }
};

这应该足以欺骗大多数需要容器的代码。在最坏的情况下,您可能需要在外观中提供额外的 typedef,即

value_type
等...


0
投票

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.