在c++ 11中遍历堆栈时,无效的范围表达式
invalid range expression when looping through stack in c++ 11
我试图在c++ 11中循环堆栈,然而,以下代码似乎无效,我可以以这种方式循环向量,为什么堆栈在这里不起作用?
#include <stack>
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
stack<int> s;
s.push(1);
s.push(2);
for (int val:s){
cout<<val<<endl;
}
return 0;
}
std::stack
不是容器(与std::vector
不同)。它是一个容器适配器。它有意地将底层容器的功能限制为仅支持堆栈操作。它没有迭代器,没有begin
或end
成员函数,这是range-for循环工作所必需的。堆栈不是用来迭代的。如果你想在集合上迭代,那么你就不需要堆栈。您需要一个序列容器,如std::vector
或std::deque
。
如果你想要的功能是某种序列容器和堆栈的混合体,(例如:支持迭代的东西,但只允许在一端插入和删除),然后您必须自己实现
因为stack
没有iterators
,也没有begin
和end
。如果你需要用迭代器堆栈,你需要自己在其他容器(std::list, std::vector等)上实现它。
std::stack没有提供begin或end成员函数,因此它不能与基于范围的for循环一起工作,而这两者都需要,我们可以从cppreference的基于范围的for循环条目中看到,它扩展为:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
:
如果__range的类型是具有begin或end成员函数的类类型,则begin_expr为__range.begin(), end_expr为__range.end();
或:
否则,begin_expr为begin(__range), end_expr为end(__range),它们是通过与std作为关联命名空间的参数相关查找找到的。
基于范围的循环产生的代码类似如下:(源代码)
//__begin, __end,__range has been used for explanation only.
{
auto && __range = range_expression ;
for (auto __begin = begin_expr,
__end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
可以看到它在下面使用了begin和end迭代器。它只对定义了begin()和end()方法的类型有效,而对于stack则不是这样。
这是一个重复问题;参见std::stack暴露迭代器吗?对于答案——std::stack没有迭代器
std::stack
提供了一个有意的限制包装容器的功能。
对于仍然需要迭代容器元素的情况,std::stack
提供包装容器作为protected
成员 c
。
protected
意味着您需要定义一个派生类,以便在不使用低级技巧的情况下访问它。下面的代码可能仍然被认为是相当低级的,但它没有任何强制类型转换,没有显式转换。在某种程度上,我认为这很好,尽管它只是利用了c++类型系统中的漏洞。
#include <stack>
#include <iostream>
using namespace std;
template< class Item >
struct Hack
: stack<Item>
{
static
auto container_of( stack<Item> const& st )
-> typename stack<Item>::container_type const&
{ return st.*(&Hack::c); }
};
namespace std
{
template< class Item >
auto begin( stack<Item> const& s )
-> decltype( Hack<Item>::container_of( s ).begin() )
{ return Hack<Item>::container_of( s ).begin(); }
template< class Item >
auto end( stack<Item> const& s )
-> decltype( Hack<Item>::container_of( s ).end() )
{ return Hack<Item>::container_of( s ).end(); }
}
auto main()
-> int
{
stack<int> s;
s.push(1);
s.push(2);
for( int const v : s ) { cout << v << endl; }
}
这个hack的优点是它可以在任何你需要迭代std::stack
的项的地方使用,例如为了调试的目的。
但是对于普通的编程,我会从std::stack
中派生出我自己的堆栈,我想这就是最初的意图。
可以这样写:
#include <stack>
#include <iostream>
using namespace std;
template< class Item >
class Stack
: public std::stack<Item>
{
protected:
using std::stack<Item>::c;
public:
auto begin() const -> decltype( c.cbegin() ) { return c.cbegin(); }
auto end() const -> decltype( c.cend() ) { return c.cend(); }
};
auto main()
-> int
{
Stack<int> s;
s.push(1);
s.push(2);
for( int const v : s ) { cout << v << endl; }
}
- 为什么在全局范围内使用"extern int a"似乎不行?
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 错误:未在此范围内声明'reverse'
- 正在将指针转换为范围
- 在 C++ 中使用正则表达式错误时出现问题 括号表达式中的范围无效
- 程序中的布尔函数返回输入的范围无论如何都是无效的
- 为什么这个正则表达式C++在括号表达式中抛出无效范围异常?
- 错误:非静态数据成员的使用无效,在此范围内未声明变量
- 在基于范围的 for 循环中获取无效引用
- 3 错误:错误:未在此范围内声明'Entry'。错误:模板参数 1 无效。错误:令牌之前声明中的类型无效'('
- 在 ipv6 链接范围单播 udp 客户端-服务器中应用 boost::asio::ip::udp,有时有效,但有时无效
- 标准::矢量::擦除无效范围
- 肯定无效的指针范围
- 无法正确验证无效输入并接受带有C++的正确范围值
- 当对象超出范围/无效时得到通知
- 为什么标准不允许 std::for_each 对无效的随机访问迭代器范围有明确定义的行为?
- 在for循环的范围中,std::valarray的范围表达式无效
- 在c++ 11中遍历堆栈时,无效的范围表达式