标签: ranged-loops

C++ 11基于反向范围的for-loop

是否有一个容器适配器可以反转迭代器的方向,所以我可以反向迭代一个容器,基于范围的for循环?

使用显式迭代器,我会将其转换为:

for (auto i = c.begin(); i != c.end(); ++i) { ...
Run Code Online (Sandbox Code Playgroud)

进入这个:

for (auto i = c.rbegin(); i != c.rend(); ++i) { ...
Run Code Online (Sandbox Code Playgroud)

我想转换这个:

for (auto& i: c) { ...
Run Code Online (Sandbox Code Playgroud)

对此:

for (auto& i: std::magic_reverse_adapter(c)) { ...
Run Code Online (Sandbox Code Playgroud)

有这样的事情还是我必须自己写?

c++ c++11 ranged-loops

309
推荐指数
8
解决办法
10万
查看次数

内部函数的ranged错误

我在C++中使用ranged有点麻烦.我正在尝试使用它来显示元素和int数组(int []),当我在main函数上执行它时,它完全正常,如:

int main(int argc, char const *argv[]) {

  int v[] = {3, 4, 6, 9, 2, 1};

  for (auto a : v) {
      std::cout << a << " ";
  }
  std::cout << std::endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到了我想要的和预期的输出,即:

3 4 6 9 2 1
Run Code Online (Sandbox Code Playgroud)

但是当我尝试在函数内部使用ranged时,事情变得有点奇怪,例如我遇到了这段代码的问题:

void printList(int *v);

int main(int argc, char const *argv[]) {

  int v[] = {3, 4, 6, 9, 2, 1};

  printList(v);

  return 0;
}

void printList(int *v) {
  for (auto a : v) {
    std::cout << …
Run Code Online (Sandbox Code Playgroud)

c++ arrays ranged-loops

14
推荐指数
3
解决办法
691
查看次数

基于矢量获取范围内的项目索引

C++ 11引入了基于范围的for循环,它使用(const)迭代器在内部实现,因此:

std::vector<std::string> vec;

for(std::string &str : vec)
{
//...
}
Run Code Online (Sandbox Code Playgroud)

基本上相当于更冗长(是的,它可以简化使用auto):

for(std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it)
{
//...
}
Run Code Online (Sandbox Code Playgroud)

然而,通常还需要项目的索引.第二种方法很简单:

auto index = it - vec.begin();
Run Code Online (Sandbox Code Playgroud)

在基于范围的情况下,for它不是那么简单.但我想知道这是否可行且可移植的解决方案完全避免了迭代器:

for(auto &str : vec)
{
    auto index = &str - &vec[0];
}
Run Code Online (Sandbox Code Playgroud)

(const版本将是相同的,但需要注意不要将非const容器与const引用混合,这可能并不总是很明显.)

显然这取决于几个假设:

  • vector的迭代器只是对项目的引用(可能在标准中?)

  • 容器保证连续(std::vector是...)

  • 基于范围的内部实现(也可能在标准中)

c++ c++11 ranged-loops

13
推荐指数
2
解决办法
888
查看次数

vc ++不再使用基于范围的语法对for循环进行简单的向量化

在用基于范围的循环替换我的许多"旧"for循环之前,我使用visual studio 2013进行了一些测试:

std::vector<int> numbers;

for (int i = 0; i < 50; ++i) numbers.push_back(i);

int sum = 0;

//vectorization
for (auto number = numbers.begin(); number != numbers.end(); ++number) sum += *number;

//vectorization
for (auto number = numbers.begin(); number != numbers.end(); ++number) {
    auto && ref = *number;
    sum += ref;
}

//definition of range based for loops from http://en.cppreference.com/w/cpp/language/range-for
//vectorization
for (auto __begin = numbers.begin(),
    __end = numbers.end();
    __begin != __end; ++__begin) {
    auto && ref = *__begin;
    sum …
Run Code Online (Sandbox Code Playgroud)

c++ vectorization visual-c++ c++11 ranged-loops

10
推荐指数
1
解决办法
474
查看次数

标准库中是否有一个概念可以测试范围 for 循环的可用性

有许多不同的方法可以使类型/类在范围 for 循环中可用。例如,在cppreference上给出了概述:

range-expression进行评估以确定要迭代的顺序或范围。序列中的每个元素依次被取消引用,并用于使用范围声明中给定的类型和名称来初始化变量。

begin_exprend_expr定义如下:

  • 如果range-expression是数组类型的表达式,则begin_expris__rangeend_expris ( __range+ __bound),其中__bound是数组中元素的数量(如果数组大小未知或类型不完整,则程序格式错误)
  • 如果是同时具有指定成员和指定成员的range-expression类类型的表达式(无论该成员的类型或可访问性如何),则is且isCbeginendbegin_expr__range.begin()end_expr__range.end()
  • 否则,begin_exprisbegin(__range)end_expris end(__range),它们是通过参数相关的查找找到的(不执行非 ADL 查找)。

如果我想在函数模板中使用范围 for 循环,我想限制类型在范围 for 循环中可用,以触发编译器错误并显示一条漂亮的“约束不满足”消息。考虑以下示例:

template<typename T>
requires requires (T arg) {
  // what to write here ??
}
void f(T arg) {
    for ( auto e : arg ) {
    } …
Run Code Online (Sandbox Code Playgroud)

c++ c++-concepts ranged-loops c++20

8
推荐指数
1
解决办法
238
查看次数

在基于范围的for循环中使用shared_ptr到std :: vector

我编写了一个c ++函数,它汇总了一些数据,然后返回一个包含数据std::shared_ptr的新分配std::vector.类似于此的东西:

std::shared_ptr<std::vector<int>> shared_ptr_to_std_vector_of_ints()
{
    auto v = std::make_shared<std::vector<int>>();
    for (int i = 0; i < 3; i++) v->push_back(i);
    return v;
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用基于范围的for循环迭代向量的内容,但它的作用就好像向量是空的.摆弄后,我发现通过将函数返回的值赋给局部变量,然后在循环中引用它,我可以使它按照我的预期运行:

// Executes loop zero times:
std::cout << "First loop:" << std::endl;
for (int i : *shared_ptr_to_std_vector_of_ints()) std::cout << i << std::endl;

// Prints three lines, as expected
std::cout << "Second loop:" << std::endl;
auto temp = shared_ptr_to_std_vector_of_ints();
for (int i : *temp) std::cout << i << std::endl;
Run Code Online (Sandbox Code Playgroud)

剪断打印这个:

First loop:
Second loop:
1 …
Run Code Online (Sandbox Code Playgroud)

c++ shared-ptr c++11 ranged-loops

7
推荐指数
1
解决办法
576
查看次数

如何迭代 mdspan?

因此,我决定使用mdspan普通跨度 + 元素访问函数的组合,而不是简单的组合。但是 - 我想对 mdspan 做的一件明显的事情是迭代它的元素。这就是我用一维跨度来实现的方法:

std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto sp = std::span(vec.data(), 12);
for (auto x : sp) {
    std::cout << x << ' ';
}
std::cout << '\n';
Run Code Online (Sandbox Code Playgroud)

...但不适用于mdspan's (使用Kokkos 实现):

std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto ms = std::mdspan(vec.data(), 12);
for (auto x : …
Run Code Online (Sandbox Code Playgroud)

c++ iteration ranged-loops c++23 mdspan

7
推荐指数
1
解决办法
744
查看次数

如何在范围表达式中延长临时的生命周期?

在使用ranged-for循环时,我正在获取悬空引用.考虑以下C++ 14表达式(下面的完整示例程序):

    for(auto& wheel: Bike().wheels_reference())
        wheel.inflate();
Run Code Online (Sandbox Code Playgroud)

它的输出是:

 Wheel()
 Wheel()
 Bike()
~Bike() with 0 inflated wheels.
~Wheel()
~Wheel()
 Wheel::inflate()
 Wheel::inflate()
Run Code Online (Sandbox Code Playgroud)

显然有些事情是非常错误的.车轮超出其使用寿命,结果为0,而不是预期的2.

一个简单的解决方法是为Bikein 引入一个变量main.但是,我不控制代码mainWheel.我只能改变结构Bike.

有没有办法通过改变来修复这个例子Bike

一个成功的解决方案解决方案要么在编译时失败,要么计算2个充气轮胎并且不会触及超出其生命周期的任何物体.

附录:编译就绪源

#include <cstdlib>
#include <iostream>
#include <array>
#include <algorithm>
using std::cout;
using std::endl;

struct Wheel
{
    Wheel() { cout << " Wheel()" << endl; }
    ~Wheel() { cout << "~Wheel()" << endl; }
    void inflate() { inflated = true; cout << " Wheel::inflate()" << …
Run Code Online (Sandbox Code Playgroud)

c++ reference ranged-loops c++14

6
推荐指数
1
解决办法
240
查看次数

基于循环和多个迭代器的范围

我有以下代码,表示3D应用程序中的网格(为清晰起见,省略了一些代码):

class Mesh {
public:
    typedef std::vector<Vertex> Vertices;
    typedef std::vector<int> Elements;

    template<class VerticesIt, class ElementsIt>
    Mesh(const VerticesIt verticesBegin,
         const VerticesIt verticesEnd,
         const ElementsIt elementsBegin,
         const ElementsIt elementsEnd) :
    vertices_(verticesBegin, verticesEnd),
    elements_(elementsBegin, elementsEnd) {
    }        
    virtual ~Mesh();

    typename Vertices::const_iterator verticesBegin() const {
        return vertices_.begin();
    };

    typename Vertices::const_iterator verticesEnd() const {
        return vertices_.end();
    };

    typename Elements::const_iterator elementsBegin() const {
        return elements_.begin();
    };

    typename Elements::const_iterator elementsEnd() const {
        return elements_.end();
    };

private:       
    Vertices vertices_;
    Elements elements_;

};
Run Code Online (Sandbox Code Playgroud)

它工作得非常好,为内部数据提供了清晰的界面.没有为容器公开实现细节.

我对此有一点打嗝.我不能使用基于范围的循环,必须使用迭代器:

for (auto it = …
Run Code Online (Sandbox Code Playgroud)

c++ iterator for-loop c++11 ranged-loops

4
推荐指数
1
解决办法
2011
查看次数

变量循环的范围导致返回局部变量的地址引用?

// g++ --std=c++17 test.cpp -I /usr/local/include -L /usr/local/lib -lboost_system -Wall -pedantic -Wreturn-type -Wstrict-aliasing -Wreturn-local-addr -fsanitize=address -g
// LD_LIBRARY_PATH=/usr/local/lib ./a.out

#include <iostream>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

class A {
public:
    fs::path path_;

    const fs::path & path() const { return path_; }
    fs::path & path() { return path_; }
};

class B {
public:
    fs::path root_path_;

    A path_2;
    A path_3;

    const fs::path & operator()() const {
        for ( const auto & path : {
            path_3.path(),
            path_2.path(),
            root_path_
        }) {
            if …
Run Code Online (Sandbox Code Playgroud)

c++ gcc ranged-loops c++17 fedora-25

4
推荐指数
1
解决办法
273
查看次数