for 循环的简写 - C++中的语法糖(11)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29512963/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 21:11:43  来源:igfitidea点击:

Shorthand for for-loop - syntactic sugar in C++(11)

c++c++11for-loopsyntaxsyntactic-sugar

提问by dingalapadum

Actually these are two related questions.

其实这是两个相关的问题。

I know there is a new syntax in C++11 for range-based forloops of the form:

我知道 C++11 中有一种新语法用于for以下形式的基于范围的循环:

//v is some container
for (auto &i: v){
   // Do something with i
}

First question: how can I infer at which iteration I am in this loop? (Say I want to fill a vector with value j at position j).

第一个问题:我如何推断我在这个循环中的哪个迭代?(假设我想在位置 j 用值 j 填充向量)。

Second question: I wanted to know if there also is some other way to write a loop of the form

第二个问题:我想知道是否还有其他方法可以编写表单的循环

for (int i=0; i<100; i++) { ... }

I find this way of writing it a bit cumbersome, and I do this so often and I would love to have a more concise syntax for it. Something along the lines:

我发现这种写法有点麻烦,而且我经常这样做,我希望有一个更简洁的语法。沿线的东西:

for(i in [0..99]){ ... }

would be great.

会很好。

For both questions I would like to avoid having to use additional libraries.

对于这两个问题,我都希望避免使用额外的库。

回答by Mike Seymour

First answer: you don't. You've used a simple construct for a simple purpose; you'll need something more complicated if you have more complicated needs.

第一个答案:你没有。您已经为一个简单的目的使用了一个简单的构造;如果您有更复杂的需求,您将需要更复杂的东西。

Second answer: You could make an iterator type that yields consecutive integer values, and a "container" type that gives a range of those. Unless you have a good reason to do it yourself, Boost has such a thing:

第二个答案:您可以创建一个生成连续整数值的迭代器类型,以及一个给出这些值范围的“容器”类型。除非你有充分的理由自己做,否则 Boost 有这样的东西

#include <boost/range/irange.hpp>

for (int i : boost::irange(0,100)) {
    // i goes from 0 to 99 inclusive
}

回答by Peter K

Use this:

用这个:

size_t pos = 0;
for (auto& i : v) {
    i = pos;
    ++pos;
}

(Boostis good, but it is not universally accepted.)

Boost是好的,但它并没有被普遍接受。)

回答by Angew is no longer proud of SO

For the first question, the answer is pretty simple: if you need the iteration count, don't use the syntactic construct which abstracts away the iteration count. Just use a normal forloop and not the range-based one.

对于第一个问题,答案非常简单:如果您需要迭代计数,请不要使用抽象出迭代计数的句法结构。只需使用普通for循环而不是基于范围的循环。

For the second question, I don't think there's anything currently in the standard library, but you could use a boost::irangefor it:

对于第二个问题,我认为标准库中目前没有任何内容,但您可以使用 a boost::irange

for (int i : boost::irange(0, 100))

回答by onqtam

For the second question - if Boostis too heavy, you could always use this library:

对于第二个问题 - 如果Boost太重,你总是可以使用这个库:

for(auto i : range(10, 15)) { cout << i << '\n'; }will print 10 11 12 13 14

for(auto i : range(10, 15)) { cout << i << '\n'; }将打印 10 11 12 13 14

for(auto i : range(20, 30, 2)) { cout << i << '\n'; }will print 20 22 24 26 28

for(auto i : range(20, 30, 2)) { cout << i << '\n'; }将打印 20 22 24 26 28

Doubles and other numeric types are supported too.

也支持双精度和其他数字类型。

It has other pythonic iteration tools and is header-only.

它有其他 pythonic 迭代工具,并且只有头文件。

回答by Matt

You can do both of these things with Boost.Range: http://boost.org/libs/range

你可以用 Boost.Range 做这两件事:http://boost.org/libs/range

For brevity (and to spice things up a little, since boost::irangehas been already demonstrated in isolation), here's a sample code demonstrating these features working together:

为简洁起见(为了让事情更有趣,因为boost::irange已经单独演示了),这里有一个示例代码,演示了这些功能一起工作:

// boost::adaptors::indexed
// http://www.boost.org/doc/libs/master/libs/range/doc/html/range/reference/adaptors/reference/indexed.html
#include <boost/range/adaptor/indexed.hpp>

// boost::irange
// http://www.boost.org/doc/libs/master/libs/range/doc/html/range/reference/ranges/irange.html
#include <boost/range/irange.hpp>

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> input{11, 22, 33, 44, 55};
    std::cout << "boost::adaptors::indexed" << '\n';
    for (const auto & element : input | boost::adaptors::indexed())
    {
        std::cout << "Value = " << element.value()
                  << " Index = " << element.index()
                  << '\n';
    }

    endl(std::cout);

    std::cout << "boost::irange" << '\n';
    for (const auto & element : boost::irange(0, 5) | boost::adaptors::indexed(100))
    {
        std::cout << "Value = " << element.value()
                  << " Index = " << element.index()
                  << '\n';
    }

    return 0;
}

Sample output:

示例输出:

boost::adaptors::indexed
Value = 11 Index = 0
Value = 22 Index = 1
Value = 33 Index = 2
Value = 44 Index = 3
Value = 55 Index = 4

boost::irange
Value = 0 Index = 100
Value = 1 Index = 101
Value = 2 Index = 102
Value = 3 Index = 103
Value = 4 Index = 104

回答by Stuck

For the 2nd question:

对于第二个问题:

There is another way, but I would not use or recommend it. However, for quickly setting up a test you could write:

还有另一种方式,但我不会使用或推荐它。但是,为了快速设置测试,您可以编写:

if you do not want to use a library and you are fine with only providing the top bound of the range you can write:

如果您不想使用库并且只提供可以编写的范围的上限就可以了:

for (auto i:vector<bool>(10)) {
    cout << "x";
}

This will create a boolean vector of size 10, with uninitialized values. Looping through these unitialized values using i(so do notuse i) it will print 10 times "x".

这将创建一个大小为 10 的布尔向量,其中包含未初始化的值。通过使用这些未初始化值循环i(所以千万不能使用i),将打印10次“×”。

回答by Yakk - Adam Nevraumont

If vis a vector (or any stdcontiguous container), then

如果v是向量(或任何std连续的容器),则

for(auto& x : v ) {
  size_t i = &x-v.data();
  x = i;
}

will set the ith entry to the value i.

将第 i 个条目设置为 value i

An output iterator that counts is reasonably easy to write. Boosthas one and has an easy-to-generate range of them called irange.

一个计数的输出迭代器相当容易编写。Boost有一个,并且有一个易于生成的范围,称为irange.

Extracting the indexes of a container is relatively easy. I have written a function called indexesthat can take a container, or a range of integers, and produces random output iterators over the range in question.

提取容器的索引相对容易。我编写了一个名为的函数indexes,它可以接受一个容器或一个整数范围,并在所讨论的范围内产生随机输出迭代器。

That gives you:

这给你:

for (size_t i : indexes(v) ) {
  v[i] = i;
}

There probably is an equivalent container-to-index range function in Boost.

Boost 中可能有一个等效的容器到索引范围函数。

If you need both, and you don't want to do the work, you can write a zipper.

如果两者都需要,又不想做这个工作,可以写一个zipper。

for( auto z : zip( v, indexes(v) ) ) {
  auto& x = std::get<0>(z);
  size_t i = std::get<1>(z);
  x = i;
}

where ziptakes two or more iterable ranges (or containers) and produces a range view over tuples of iterator_traits<It>::references to the elements.

wherezip需要两个或多个可迭代范围(或容器),并生成iterator_traits<It>::references元组到元素的范围视图。

Here is Boost zip iterator: http://www.boost.org/doc/libs/1_41_0/libs/iterator/doc/zip_iterator.html-- odds are there is a Boost zip range that handles syntax like the above zipfunction.

这是 Boost zip 迭代器:http: //www.boost.org/doc/libs/1_41_0/libs/iterator/doc/zip_iterator.html—— 可能有一个 Boost zip 范围可以处理类似上述zip函数的语法。

回答by Sheen

For the second question, if you are using the latest Visual Studio versions, type 'if' then Tab, Tab, and Tabto fill in init value, step-up and so on.

对于第二个问题,如果您使用的是最新的 Visual Studio 版本,请键入 'if' then TabTab、 并Tab填写 init 值、step-up 等。