1

我有一个类,它有一个双端队列,它用作堆栈(可能是一个向量,只是碰巧选择了双端队列)。

无论如何,我希望允许消费者迭代堆栈的内容(这是 std::stack 无法做到的)。我目前正在使用 push_back() 将项目推入堆栈,因此如果一个以前向顺序迭代内容,则一个从堆栈底部到顶部。

我宁愿以相反的顺序公开事物,以便使用 for (auto e: thestack) 以自上而下的方式迭代堆栈。

我发现了C++11 反向基于范围的 for 循环,它显示了一些用于反转新 for 循环语法(以及基于范围的算法)的迭代顺序的解决方案。

我不清楚的是如何提供一个简单的机制来让我的用户访问这个自动反转的双端队列。

例如,无需任何实际努力,我可以简单地允许 const& 访问底层双端队列:

  const std::deque<T> & GetStack() const { return m_stack; }

消费者可能负责逆转:

  for (auto e : reverse(m_toolstack.GetStack()))

在这里,我尝试使用以下解决方案进行反向:

template<class Fwd>
struct reverser_generic 
{
    Fwd &fwd;
    reverser_generic(Fwd& fwd_): fwd(fwd_) {}
    typedef std::reverse_iterator<typename Fwd::iterator> reverse_iterator;
    reverse_iterator begin() { return reverse_iterator(std::end(fwd)); } 
    reverse_iterator end() { return reverse_iterator(std::begin(fwd)); } 
};

template<class Fwd>
struct reverser_special
{
    Fwd &fwd;
    reverser_special(Fwd& fwd) : fwd(fwd) { }
    auto begin() -> decltype(fwd.rbegin()) { return fwd.rbegin(); } 
    auto end() -> decltype(fwd.rend()) { return fwd.rend(); } 
};

template<class Fwd>
auto reverse_impl(Fwd& fwd, long) -> decltype(reverser_generic<Fwd>(fwd))
{ 
    return reverser_generic<Fwd>(fwd);
}

template<class Fwd>
auto reverse_impl(Fwd& fwd, int) -> decltype(fwd.rbegin(), reverser_special<Fwd>(fwd))
{ 
    return reverser_special<Fwd>(fwd);
}

template<class Fwd>
auto reverse(Fwd&& fwd) -> decltype(reverse_impl(fwd,int(0))) 
{
    static_assert(!(std::is_rvalue_reference<Fwd&&>::value), "Cannot pass an rvalue reference to reverse()");
    return reverse_impl(fwd,int(0));
}

以上所有内容都可以使用 VS2012 正确编译和运行(感谢 Jive Dadson 等人的解决方案)。

然而,在我的堆栈外观中,我真的很想简单地总是返回底层容器的反向,但我不清楚如何以一种明智的方式这样做:

auto GetContents() const -> decltype(reverse(m_stack)) { return reverse(m_stack); }

上面的错误,说明m_stack是未知的。this->m_stack 同样未知。

我该如何返回“无论是我的成员 m_stack 的反面是什么”?

请注意,一旦得到回答,我还需要“如何返回反向(m_stack)的decltype的const&?

4

1 回答 1

1

是在声明GetContents之前声明的m_stack吗?

后期指定的返回类型中的名称必须遵守与函数签名其余部分中的名称相同的规则,即它们不能引用尚未声明的类成员:

struct X
{
    auto f() -> decltype(m_x) { return m_x; }  // ERROR
    int m_x;
    auto g() -> decltype(m_x) { return m_x; }  // OK
};

要使其工作,要么使用std::declvalto 引用类型(这意味着如果您将from的GetContents类型更改为,则必须更新签名)或确保在引用之前已声明。m_stackstd::dequestd::vectorm_stack

于 2013-02-12T17:29:59.250 回答