Я пытаюсь сделать следующее:
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>?
@PasserBy std::execution::...?
@PasserBy Полностью согласен! Но я думаю, что есть некоторая польза от возможности использовать большое количество возможностей языка. Я хотел попробовать это, потому что это тривиально для циклов for в стиле c и, похоже, я смогу сделать это с помощью std::for_each_n.
@TedLyngmo Хорошо, я тебе это дам. Я имел в виду случаи, когда это просто замена обычных циклов, как в данном случае.
Политики выполнения @TedLyngmo поддерживают только параллельный и последовательный цикл. Я не думаю, что здесь есть что-то подходящее для моего варианта использования.
@PasserBy на самом деле стоит отметить: они упрощают многопоточные циклы. Хотя, должен признаться, я никогда не видел, чтобы это использовалось.
@Eshy «Я никогда не видел, чтобы это использовалось» — какой вариант C++ 17 (или более поздних версий) вы видели вместо этого?
По теме: Почему вы считаете условный оператор решающим в этом сценарии? Почему бы и нет: if (condition) { /* do this */ } else { /* do that */ }?
@TedLyngmo Я имел в виду, что раньше не видел, чтобы каждая итерация цикла была распараллелена. Я видел обработку кода, анализирующего большие файлы изображений по частям. Однако там распараллеливание выполнялось вручную. Файл был разделен на фрагменты в зависимости от его размера, и каждый фрагмент в конце был объединен. Тем не менее, я не являюсь профессией или чем-то еще (вероятно, вы можете понять это по вопросу).
Политики выполнения @Eshy обычно работают хорошо, если применяются во внешнем цикле. Мельчайшие детали внутри обычно изготавливаются вручную, и если все сделано правильно, внешняя синхронизация не потребуется.
@TedLyngmo, потому что мне нравится сохранять константность, если только она не требует изменения. Другой способ инициализировать начало — это немедленный вызов лямбды, что здесь кажется излишним. Если вы имеете в виду, почему я не делаю просто два цикла for, то это потому, что, насколько я понимаю, цель стандартной библиотеки — сделать код выразительным и компактным. Было бы гораздо разумнее просто использовать цикл в стиле C, если мой единственный другой вариант — написать вдвое больше кода. Мотивация моего вопроса состоит в том, чтобы узнать, существует ли способ сделать это с помощью стандартной библиотеки. Я не утверждаю, что это лучшая практика.
@TedLyngmo Это очень хороший момент! У меня просто нет опыта работы с cpp, чтобы столкнуться с такой ситуацией. Хотя я сохраню это в глубине души!
«почему бы мне просто не сделать два цикла for» — вы можете написать один цикл, который при создании экземпляра превращается в два цикла. Когда дело доходит до стандартной библиотеки, ее использование часто становится шаблоном функции.
@TedLyngmo Извините, я не уверен, что полностью понимаю, что вы имеете в виду. Вы имеете в виду абстрагировать цикл в шаблонную функцию и выполнять его с другим аргументом шаблона в зависимости от условия?
@Eshy «шаблоновая функция» — да, за исключением того, что шаблонных функций нет. Есть только шаблоны функций. Это языковая деталь, которая имеет большое значение, когда дело доходит до объяснения создания экземпляров.
@TedLyngmo, понятно. Тогда я мог бы придерживаться реализации в стиле c. Наличие двух функций, одна из которых является шаблоном функции, кажется здесь совершенно неразумным. Спасибо за дискуссию!
@Eshy Пожалуйста. Если вы предоставите рабочую реализацию в стиле C @ codereview и пометите ее как C++, кто-то может предложить альтернативу, которая не покажется необоснованной.





Вам придется создать новую шаблонную функцию, чтобы выполнить итерацию, чтобы справиться с разными типами. Вы можете немного сократить это, используя лямбду:
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());
}
Я никогда не видел смысла использовать
std::for_eachи до сих пор не вижу.