我写了一个简短的实用程序函数,一个对象来“包装”一个可迭代的容器,这样我就可以使用基于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
的对象支持迭代需要什么?解决这个问题的最佳方法是什么?
答案 0 :(得分:4)
为iterables选择begin
和end
函数的实际规则如下:如果它有一些,请使用类begin
和end
函数。如果提供了一些函数,请使用全局函数std::begin
和std::end
的重载。
静态数组不是class / struct,它们没有/不能有成员函数。 foreach循环调用的函数是全局函数std::begin
和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::rbegin
和std::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));
}
答案 1 :(得分:2)
在您的代码中,Iterable
模板参数需要具有begin
和end
成员函数。普通C ++数组没有这些功能。相反,您必须使用std::begin
和std::end
,它们是C ++ 11标准的一部分。
但是,似乎没有任何std::rbegin
或std::rend
函数,这意味着您必须自己实现这些函数,也可能实现实际的迭代器类。