Итератор для развертывания вложенных циклов в C++C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Итератор для развертывания вложенных циклов в C++

Сообщение Anonymous »

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

Код: Выделить всё

struct vec2f {
float x, y;
};

void each_to_each(std::vector& vec)
{
std::for_each(std::begin(vec), std::end(vec), [&]([[maybe_unused]] const auto& pos1) {
const auto it = std::begin(vec) + (&pos1 - std::data(vec));
std::for_each(it + 1, std::end(vec), [&]([[maybe_unused]] const auto& pos2) {
// Some actions with pos1 and pos2 (like particles interaction)
});
});
}

void each_to_each_symmetrical(std::vector& vec)
{
std::for_each(std::begin(vec), std::end(vec), [&]([[maybe_unused]] const auto& pos1) {
std::for_each(std::begin(vec), std::end(vec), [&]([[maybe_unused]] const auto& pos2) {
if (&pos1 == &pos2) {
return;
}

// Some actions with pos1 and pos2 (like particles interaction)
});
});
}
Что мне не нравится из-за слишком многословного синтаксиса, трудностей с выходом из внутреннего цикла, вложенных скобок и т. д.
Итак, типичный способ избежать этого — поместить эти циклы в обертку:

Код: Выделить всё

template
void each_to_each_with_functor(std::vector& vec, Functor fn)
{
std::for_each(std::begin(vec), std::end(vec), [&](const auto& pos1) {
const auto it = std::begin(vec) + (&pos1 - std::data(vec));
std::for_each(it + 1, std::end(vec), [&](const auto& pos2) {
fn(pos1, pos2);
});
});
}

void foo([[maybe_unused]]const vec2f& pos1, [[maybe_unused]] const vec2f& pos2) {
// Some actions with pos1 and pos2 (like particles interaction)
}
Это работает нормально, но сохраняет проблему с выходом из вложенного цикла и дополнительно вызывает проблему с передачей контекста (локальных переменных, определенных перед циклом) в функцию; когда их много, это слишком многословно. Иногда производительность также может быть проблемой.
Моя идея состоит в том, чтобы реализовать для него своего рода итератор и обертку, которая будет инкапсулировать обработку вложенных циклов (с парой итераторов) и которая будет иметь возможность работать в одноуровневом цикле для разработчика.
Итак, использование должно быть таким:

Код: Выделить всё

    std::vector vec;
NestedLoopIterator loop = NestedLoopIterator(vec.begin(),vec.end());

std::for_each(loop.begin(), loop.end(), [&](const auto& its) {
const vec2f& pos1 = its.it1;
const vec2f& pos2 = its.it2;

// Some actions with pos1 and pos2 (like particles interaction)
});
Он может определять стратегии обхода (например, две, показанные в начале вопроса), обрабатывать многопоточность, можно настраивать уровни вложенности и т. д.
Во избежание изобретения велосипеда, известна ли реализация такого итератора?
Если нет, и вы видите существенные недостатки такого решения и недостатки в предлагаемом проекте проекта, поделитесь своим мнением. . Я до сих пор не уверен, хорошая ли это идея и что ее преимущества перевесят возникшую сложность.
Вот демо-версия без реализации NestedLoopIterator на данный момент.

Подробнее здесь: https://stackoverflow.com/questions/790 ... lling-in-c
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»