是否可以替换(自动 i=0;i<n;i++) ... with for(auto i:<something>) 而不使用向量?
Is it possible to replace for(auto i=0;i<n;i++) ... with a for(auto i:<something>) without using a vector?
我想替换一个简单的 for 循环:
for (auto i=0;i<n;i++) {
whatever;
}
使用以下形式的迭代器:
for (auto i: <something>) ...
我知道可以用向量来完成,但我不想声明一个向量(并填充它)。
从理论上讲,我想要这样简单的东西:
for (auto i: 1..n) ...
这可能吗?
谢谢。
没有内置的解决方案。
如果需要,可以使用如下Boost.counting_range:
#include <iostream>
#include <boost/range/counting_range.hpp>
int main() {
for (auto v : boost::counting_range(2,13))
std::cout << v << "n";
}
(直播)或自己滚动。提升范围不会保存所有数字,而是包装一对迭代器。(在概念上类似于 Python2 xrange
或 Python3 range
。
现在,这是否比手动编写循环更容易/更好,由读者决定。
附录:如果你想推出自己的解决方案,请编写一些迭代器,在取消引用时返回一个数字,在增量时增加内部数字,如果内部数字相等,则比较相等。然后编写一个包装类,该类提供begin
和end
函数以返回此类迭代器。
Boost.counting_iterator是此类迭代器的实现,Boost.counting_range将其包装为如上所示的范围。
template<class T>
struct index_it{
T t;
void operator++(){++t;}
T operator*()const{ return t; }
friend bool operator==(index_it const& lhs,index_it const& rhs){
return lhs.t==rhs.t;
}
friend bool operator!=(index_it const& lhs,index_it const& rhs){
return lhs.t!=rhs.t;
}
};
template<class T>
index_it<T> index(T t){return {t}; }
这是一个非常小的索引"迭代器"。 它不是真正的迭代器,因为它违反了他们的公理:但它保证足以进行for(:)
循环。
template<class It>
struct range_t{
It b,e;
It begin()const{return b;}
It end()const{return e;}
};
template<class It>
range_t<It> range(It b, It e){ return {b,e}; }
是一个非常小的范围,符合for(:)
循环的条件。
template<class Scalar>
auto indexes(Scalar b, Scalar e){
return range(index(b),index(e));
}
创建一系列索引。
用:
for(auto i:indexes<int>(0,n))
为了好玩,这也给了我们:
template<class R>
auto iterators(R& r){
using std::begin; using std::end;
return indexes( begin(r), end(r) );
}
这使您可以像这样迭代容器或范围的有效迭代器。 一旦你弄清楚index_it
到底是什么,问题就是一样的!
for(auto it:iterators(vec))
活生生的例子。
没有内置的解决方案。就这样。
您可以为自己定义类似的东西,如下所示:
#include<functional>
#include<cstddef>
#include<array>
#include<iostream>
template<std::size_t... I>
constexpr auto seq(std::integer_sequence<std::size_t, I...>) {
return std::array<std::size_t, sizeof...(I)>{ I... };
}
template<std::size_t N>
constexpr auto seq() {
return seq(std::make_index_sequence<N>());
}
int main() {
for(auto i: seq<10>()) {
std::cout << i << std::endl;
}
}
如果要处理 0 到 N 以外的范围,可以改为执行以下操作:
#include<functional>
#include<cstddef>
#include<array>
#include<iostream>
template<std::size_t N, std::size_t... I>
constexpr auto seq(std::integer_sequence<std::size_t, I...>) {
return std::array<std::size_t, sizeof...(I)>{ (N+I)... };
}
template<std::size_t N, std::size_t M, std::enable_if_t<(N<M)>* = nullptr>
constexpr auto seq() {
return seq<N>(std::make_index_sequence<M-N>());
}
int main() {
for(auto i: seq<3, 7>()) {
std::cout << i << std::endl;
}
}
请注意,此解决方案需要 C++14 修订版。
另一个不需要实例化数据结构的解决方案是以下解决方案:
#include<functional>
#include<cstddef>
#include<array>
#include<iostream>
#include<utility>
template<std::size_t N, typename F, std::size_t... I>
constexpr void seq(F &&f, std::integer_sequence<std::size_t, I...>) {
int arr[] = { (std::forward<F>(f)(I+N), 0)... };
}
template<std::size_t N, std::size_t M, typename F, std::enable_if_t<(N<M)>* = nullptr>
constexpr void seq(F &&f) {
seq<N>(std::forward<F>(f), std::make_index_sequence<M-N>());
}
int main() {
seq<3, 7>([](int i){
std::cout << i << std::endl;
});
}
arr
可能会被编译器清除,但它看起来不太像 for 循环。
相关文章:
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- 为什么标准首选圆括号初始化为"make_<something>"?
- 如何显式调用运算符<<
- 模板操作员&lt;未打电话
- C / CUDA中的模板方法是3个角括号(&lt;&lt;&lt;)
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 错误:调用"std::vector<:vector<int>>::p ush_back(std::vector<std::__cxx11::basic_string<
- 什么是使用something::something:something mean(c++)
- C 建造者Clang STD :: Sill,找不到超载的操作员&lt;
- 为什么STD :: MAP需要操作员&lt;以及我如何写一个
- 为什么“操作员”需要const但不是为“运营商&lt;”
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 左角支架解释为操作员&lt;而不是模板参数
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型