cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

for для нескольких контейнеров #459

Closed XRay3D closed 2 years ago

XRay3D commented 3 years ago

Вместо классического цикла с переменной ++i доработать range based for для нескольких контейнеров и соответственно итерироваться до границ наименьшего из них.

Eсли переданы std::array или обычные массивы фиксированной длины размеры которых не равны выдавать варнинг времени компиляции.

Было:

void MeasureModel::setRowsEnabled(const std::vector<Qt::CheckState>& checkStates) {
    for (int i = 0; i < RowCount; ++i) {
        if(m_rowEnabled[i] != checkStates[i]) {
            m_rowEnabled[i] = checkStates[i];
            emit dataChanged();
        }
    }
}

стало

void MeasureModel::setRowsEnabled(const std::vector<Qt::CheckState>& checkStates)
{
    for (auto& checkStateDst, auto checkStateSrc : m_rowEnabled, checkStates) {
        if (checkStateDst != checkStateSrc) {
            checkStateDst = checkStateSrc;
            emit dataChanged();
        }
    }
}
XRay3D commented 3 years ago

Моё предложение чем то похоже на #455 но более очевидно и интуитивно. Но вместо расширения с поморью библиотек немного дорабатывает сам язык, на уровне компилятора возможно провести больше оптимизаций как мне кажется.

nitrofox commented 3 years ago

В range есть похожая штука. godbolt

#include <fmt/format.h>

#include <array>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/zip.hpp>
#include <vector>
namespace rv = ranges::views;
int main() {
  std::vector<int> vi{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  std::vector<std::string> const vs{"hello", "goodbye", "hello", "goodbye"};

  for (auto [n, s] : rv::zip(vi, vs)) {
    fmt::print("n: {} | s: {}\n", n, s);
  }
  for (auto [n, s] : rv::zip(rv::iota(4), vs)) {
    fmt::print("n: {} | s: {}\n", n, s);
  }
}
XRay3D commented 3 years ago

В range есть похожая штука. godbolt

Это хорошо но всё же хотелось иметь это в компиляторе, а не таскать внешние библиотеки. Надо будет проверить на присваивание к "забиденным" полям.

nitrofox commented 3 years ago

Это хорошо но всё же хотелось иметь это в компиляторе, а не таскать внешние библиотеки.

Range частично впихнули в С++20 . Но в стандарт не вошел zip. Может в С++23 добавят.

unterumarmung commented 2 years ago

Это хорошо но всё же хотелось иметь это в компиляторе, а не таскать внешние библиотеки. Надо будет проверить на присваивание к "забиденным" полям.

Ваше решение плохо тем, что это языковое изменение, а не библиотечное. Будем надеяться, что ranges к С++23 доделают и zip туда добавят

apolukhin commented 2 years ago

В C++23 приняли std::views::zip

Теперь можно делать так

std::vector v1 = {1, 2};
std::vector v2 = {'a', 'b', 'c'};

for (auto [first, second] :  std::views::zip(v1, v2))  // ...