Любой способ перебрать вектор в обратном или прямом направлении в зависимости от условия?

Я пытаюсь сделать следующее:

const bool b_condition = false;
const auto begin = b_condition ? arr.cbegin() : arr.crbegin();
// Will likely be different than arr.size(). Simplified here for example
const int size = arr.size();

std::for_each_n(begin, size, [](const Data& d) {
    // ...
});

Мне нужно напечатать последний или первый size элементы вектора. Будет ли оно последним или первым, зависит от b_condition.

const auto begin = b_condition ? arr.cbegin() : arr.crbegin();

Приведенный выше код, конечно, не работает, поскольку const_reverse_iterator и const_iterator — разные типы, и в переменной можно сохранить только один.

После некоторых исследований, похоже, не существует общего базового класса для итераторов, поэтому я не могу его использовать. Кроме того, я понимаю, что это чрезвычайно легко сделать с помощью обычного (не стандартного) цикла for, но я пытаюсь посмотреть, смогу ли я выполнить это с помощью стандартной библиотеки, поэтому я бы предпочел ответ на основе стандартного стандарта.

Есть ли способ перебрать последний или первый элемент size на основе условия с <algorithms>?

Я никогда не видел смысла использовать std::for_each и до сих пор не вижу.

Passer By 18.04.2024 07:42

@PasserBy std::execution::...?

Ted Lyngmo 18.04.2024 07:43

@PasserBy Полностью согласен! Но я думаю, что есть некоторая польза от возможности использовать большое количество возможностей языка. Я хотел попробовать это, потому что это тривиально для циклов for в стиле c и, похоже, я смогу сделать это с помощью std::for_each_n.

Eshy 18.04.2024 07:45

@TedLyngmo Хорошо, я тебе это дам. Я имел в виду случаи, когда это просто замена обычных циклов, как в данном случае.

Passer By 18.04.2024 07:46

Политики выполнения @TedLyngmo поддерживают только параллельный и последовательный цикл. Я не думаю, что здесь есть что-то подходящее для моего варианта использования.

Eshy 18.04.2024 07:46

@PasserBy на самом деле стоит отметить: они упрощают многопоточные циклы. Хотя, должен признаться, я никогда не видел, чтобы это использовалось.

Eshy 18.04.2024 07:47

@Eshy «Я никогда не видел, чтобы это использовалось» — какой вариант C++ 17 (или более поздних версий) вы видели вместо этого?

Ted Lyngmo 18.04.2024 07:53

По теме: Почему вы считаете условный оператор решающим в этом сценарии? Почему бы и нет: if (condition) { /* do this */ } else { /* do that */ }?

Ted Lyngmo 18.04.2024 07:59

@TedLyngmo Я имел в виду, что раньше не видел, чтобы каждая итерация цикла была распараллелена. Я видел обработку кода, анализирующего большие файлы изображений по частям. Однако там распараллеливание выполнялось вручную. Файл был разделен на фрагменты в зависимости от его размера, и каждый фрагмент в конце был объединен. Тем не менее, я не являюсь профессией или чем-то еще (вероятно, вы можете понять это по вопросу).

Eshy 18.04.2024 08:03

Политики выполнения @Eshy обычно работают хорошо, если применяются во внешнем цикле. Мельчайшие детали внутри обычно изготавливаются вручную, и если все сделано правильно, внешняя синхронизация не потребуется.

Ted Lyngmo 18.04.2024 08:06

@TedLyngmo, потому что мне нравится сохранять константность, если только она не требует изменения. Другой способ инициализировать начало — это немедленный вызов лямбды, что здесь кажется излишним. Если вы имеете в виду, почему я не делаю просто два цикла for, то это потому, что, насколько я понимаю, цель стандартной библиотеки — сделать код выразительным и компактным. Было бы гораздо разумнее просто использовать цикл в стиле C, если мой единственный другой вариант — написать вдвое больше кода. Мотивация моего вопроса состоит в том, чтобы узнать, существует ли способ сделать это с помощью стандартной библиотеки. Я не утверждаю, что это лучшая практика.

Eshy 18.04.2024 08:08

@TedLyngmo Это очень хороший момент! У меня просто нет опыта работы с cpp, чтобы столкнуться с такой ситуацией. Хотя я сохраню это в глубине души!

Eshy 18.04.2024 08:09

«почему бы мне просто не сделать два цикла for» — вы можете написать один цикл, который при создании экземпляра превращается в два цикла. Когда дело доходит до стандартной библиотеки, ее использование часто становится шаблоном функции.

Ted Lyngmo 18.04.2024 08:11

@TedLyngmo Извините, я не уверен, что полностью понимаю, что вы имеете в виду. Вы имеете в виду абстрагировать цикл в шаблонную функцию и выполнять его с другим аргументом шаблона в зависимости от условия?

Eshy 18.04.2024 08:13

@Eshy «шаблоновая функция» — да, за исключением того, что шаблонных функций нет. Есть только шаблоны функций. Это языковая деталь, которая имеет большое значение, когда дело доходит до объяснения создания экземпляров.

Ted Lyngmo 18.04.2024 08:20

@TedLyngmo, понятно. Тогда я мог бы придерживаться реализации в стиле c. Наличие двух функций, одна из которых является шаблоном функции, кажется здесь совершенно неразумным. Спасибо за дискуссию!

Eshy 18.04.2024 08:24

@Eshy Пожалуйста. Если вы предоставите рабочую реализацию в стиле C @ codereview и пометите ее как C++, кто-то может предложить альтернативу, которая не покажется необоснованной.

Ted Lyngmo 18.04.2024 08:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
17
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам придется создать новую шаблонную функцию, чтобы выполнить итерацию, чтобы справиться с разными типами. Вы можете немного сократить это, используя лямбду:

const bool b_condition = false;

const int size = arr.size();
auto iterate = [&](auto begin) {
  std::for_each_n(begin, size, [](const Data& d) {
    //print d
  });
};
if (b_condition)
{
  iterate(arr.cbegin());
}
else 
{
  iterate(arr.crbegin());
}

Другие вопросы по теме