Диапазон C для цикла на основе вектора указателей. Как захватить элементы по постоянной ссылке?

#c

#c

Вопрос:

Как я могу захватить элементы по постоянной ссылке в цикле for на основе диапазона над вектором, содержащим указатели?

 #include <iostream>
#include <memory>
#include <vector>

class Foo {
public:
    Foo(int a) : a{a} {}
    int value() const { return a; }
private:
    int a;
};

int main() {
    std::unique_ptr<Foo> f1 = std::make_unique<Foo>(1);
    std::unique_ptr<Foo> f2 = std::make_unique<Foo>(2);
    std::vector<Foo *> v;
    v.push_back(f1.get());
    v.push_back(f2.get());
    //for (const Foo amp;f : v) {  // <-- This does not work..
    //    std::cout << f.value() << 'n';
    //}
    for (Foo *f_ptr : v) {
        const Foo amp;f = *f_ptr;  // <-- I would like to avoid this
        std::cout << f.value() << 'n';
    }

    return 0;
}
  

Я бы хотел избежать создания отдельной переменной только для построения ссылки:

     for (Foo *f_ptr : v) {
        const Foo amp;f = *f_ptr;  // <-- I would like to avoid this
        // ...
    }
  

Возможно ли f назначить непосредственно в условие цикла for? Например, что-то вроде:

 for (const Foo amp;f ...) { }
  

Комментарии:

1. Почему бы не использовать -> , чтобы вы могли просто иметь std::cout << f->value() << 'n'; и не нуждаться в ссылке?

2. Что не так f_ptr->value() в цикле?

3.boost::adaptors::indirected?

Ответ №1:

Вектор содержит указатели, так что это то, что вы получаете. Если вы хотите что-то еще, вам нужно выполнить цикл над другим объектом.

C 20 ranges предлагает способ сделать это. Было бы не очень сложно создать свой собственный вариант.

 #include <iostream>
#include <memory>
#include <vector>
#include <ranges>

class Foo {
public:
    Foo(int a) : a{a} {}
    int value() const { return a; }
private:
    int a;
};

int main() {
    std::unique_ptr<Foo> f1 = std::make_unique<Foo>(1);
    std::unique_ptr<Foo> f2 = std::make_unique<Foo>(2);
    std::vector<Foo *> v;
    v.push_back(f1.get());
    v.push_back(f2.get());

    for (const autoamp; f : std::ranges::views::transform(v, [](auto ptr) -> const Fooamp; { return *ptr; })) {
        std::cout << f.value() << 'n';
    }

    return 0;
}