【问题标题】:How do I create a range from a begin and end iterator?如何从开始和结束迭代器创建范围?
【发布时间】:2016-12-21 17:05:44
【问题描述】:

我有一个对象,它具有获取开始和结束迭代器的功能:

const_iterator err_begin() const
const_iterator err_end() const 

因为它们没有被命名为 beginend,所以我无法将我的对象直接传递给 range-v3 中的函数。

是否有一个简单的包装器可以让这个对象与 range-v3 库一起使用?

例如:

auto hasErrors = !empty(something(x.err_begin(), x.err_end())); 

【问题讨论】:

  • 添加begin()end()分别调用这两个函数?
  • 对象是库的一部分。我无法更改方法名称或添加新方法。
  • 创建您正在谈论的简单包装器,将开始和结束调用映射到您想要的调用。
  • 为您的对象添加重载到 beginend 函数。它们不需要是方法
  • class_name::const_iterator begin(class_name& obj) { return obj.err_begin(); }

标签: c++ range-v3


【解决方案1】:

听起来你在找iterator_range

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

【讨论】:

  • iterator_range 的文档生活在 here。只需致电ranges::make_iterator_range(x.err_begin(), x.err_end())
  • 我无法再从代码中找到iterator_rangemake_iterator_range。改名了吗?
  • @EricNiebler,为什么我们需要iterator_range,而我们可以简单地创建一个range 的迭代器?..
  • 啊,您是否使用 Microsoft fork of range-v3 for MSVC?在那个(非常过时的)分叉中,iterator_range 被称为range。它不再是了。
  • 对于未来的读者:在 C++20 中 std::ranges::subrange 似乎已替换 ranges:make_iterator_range
【解决方案2】:

您澄清说,所讨论的类是您无法更改的库的一部分。美好的。创建外观类:

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 等...

【讨论】:

  • 此类型不是Regular。它与 range-v3 库的其余部分不能很好地配合。下面布赖恩的答案是正确答案。 (我是 range-v3,FWIW 的作者。)
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多