【问题标题】:Constructing an object that can be iterated using a range based for构造一个可以使用基于范围迭代的对象
【发布时间】:2012-07-19 19:43:38
【问题描述】:

我编写了一个简短的实用函数,一个对象来“包装”一个可迭代的容器,这样我就可以使用基于范围的for 向后遍历它。

template <typename Iterable>
struct ReverseWrapper {
private:
  Iterable& m_iterable;

public:
  ReverseWrapper(Iterable& iterable) : m_iterable(iterable) {}

  auto begin() const ->decltype(m_iterable.rbegin()) {
    return m_iterable.rbegin();
  }

  auto end() const ->decltype(m_iterable.rend()) {
    return m_iterable.rend();
  }
};

template <typename Iterable>
ReverseWrapper<Iterable> reverseIterate(Iterable& list) {
  return ReverseWrapper<Iterable>(list);
}

这适用于 C++ 可迭代对象,但不适用于静态数组。对象需要什么才能支持使用基于范围的for 进行迭代?解决这个问题的最佳方法是什么?

【问题讨论】:

  • +1 我认为这将成为一个有用的标准组件。
  • 只需调用它reversed 即可获得类似 Python 的函数:p
  • 为了完整起见,我已经编辑了我的答案以通过完美的转发和功能rbeginrend 改进它。

标签: c++ arrays for-loop c++11 iterator


【解决方案1】:

为可迭代对象选择beginend 函数的实际规则如下:使用类beginend 函数(如果有的话)。如果提供了一些全局函数std::beginstd::end,请使用它们的重载。

静态数组不是类/结构,它们没有/不能有成员函数。 foreach 循环调用的函数是全局函数std::beginstd::end,以数组为参数。假设 std::rbeginstd::rend 存在,您必须按以下方式构建包装器:

template <typename Iterable>
struct ReverseWrapper {
private:
  Iterable& m_iterable;

public:
  ReverseWrapper(Iterable&& iterable) : m_iterable(iterable) {}

  auto begin() const -> decltype(rbegin(m_iterable)) {
    return rbegin(m_iterable);
  }

  auto end() const -> decltype(rend(m_iterable)) {
    return rend(m_iterable);
  }
};

template<typename Iterable>
auto reverseIterate(Iterable&& list)
    -> ReverseWrapper<Iterable>
{
    return ReverseWrapper<Iterable>(std::forward<Iterable>(list));
}

尽管std::rbeginstd::rend 存在于c++14 标准中,但它们在c++11 标准中不可用。因此,要使上述代码与 c++11 一起使用,您必须手动实现这些功能:

template<typename T, std::size_t N>
auto rbegin(T (&array)[N])
    -> std::reverse_iterator<T*>
{
    return std::reverse_iterator<T*>(std::end(array));
}

template<typename T, std::size_t N>
auto rend(T (&array)[N])
    -> std::reverse_iterator<T*>
{
    return std::reverse_iterator<T*>(std::begin(array));
}

【讨论】:

  • std::rbeginstd::rend 似乎不存在。
  • @OmnipotentEntity 是的,我意识到了。我会进行编辑,以免读者感到困惑。
  • POD 可以有成员函数,但不能有虚拟函数。
【解决方案2】:

在您的代码中,Iterable 模板参数需要具有beginend 成员函数。普通 C++ 数组没有这些功能。相反,您必须使用 std::beginstd::end,它们是 C++11 标准的一部分。

但是,似乎没有任何 std::rbeginstd::rend 函数,这意味着您必须自己实现这些,可能还要实现实际的迭代器类。

【讨论】:

    猜你喜欢
    • 2019-10-06
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 2014-09-13
    • 2017-03-20
    • 2020-12-22
    • 2011-06-01
    相关资源
    最近更新 更多