3

我写了一个简短的实用函数,一个对象来“包装”一个可迭代的容器,这样我就可以使用基于范围的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?解决这个问题的最佳方法是什么?

4

2 回答 2

4

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

静态数组不是类/结构,它们没有/不能有成员函数。foreach 循环调用的函数是全局函数std::beginand std::end,以数组为参数。假设std::rbegin并且std::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));
}

尽管存在于 c++14 标准中std::rbeginstd::rend但它们在 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));
}
于 2012-07-20T14:01:54.770 回答
2

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

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

于 2012-07-20T14:09:43.557 回答