Итерация более чем на один раз. контейнер в С++ 11

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

int main() {
  int size = 3;
  std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };

  // old-fashioned - ok
  for (int i = 0; i < size; i++) {
    std::cout << v1[i] << " " << v2[i] << std::endl;
  }

  // would like to do the same as above with auto range-for loop
  // something like this - which would be fine for ONE vector.
  // But this does not work. Do I need a hand-made iterator instead?
  for (const auto& i:v1,v2) {
    std::cout << i << " " << i << std::endl;
  }

  return EXIT_SUCCESS;
}

Спасибо!

Ответ 1

Цикл for на основе диапазона был разработан как удобство для итерации одного диапазона, потому что это, безусловно, самый распространенный случай. Если вам нужно повторить несколько диапазонов, что не является наиболее распространенным случаем, вы все равно можете сделать это традиционным способом:

for (auto i1 = begin(v1), i2 = begin(v2), e = end(v1); i1 != e; ++i1, ++i2)
{
  // processing
}

Ответ 2

В Boost.Range есть boost::combine(), что позволяет писать

#include <iostream>
#include <iterator>
#include <vector>
#include <boost/range/combine.hpp>

int main()
{
    std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };

    for (auto&& t : boost::combine(v1, v2))
            std::cout << t.get<0>() << " " << t.get<1>() << "\n";    
}

Пример Live.

Если вы не любите полагаться на это, вы можете полностью описать функциональность combine() Boost.Iterator zip_iterator и Boost.Range iterator_range и немного С++ 14 выводили возвращаемые типы:

template<class... Ranges>
auto combine(Ranges const&... ranges) 
// add -> decltype( boost::make_iterator_range(...) ) in C++11
{
    return boost::make_iterator_range(
        boost::make_zip_iterator(boost::make_tuple(begin(ranges)...)),
        boost::make_zip_iterator(boost::make_tuple(end(ranges)...))        
    );
}

Пример Live.

Объяснение: boost::make_zip_iterator создает boost::tuple итераторов в ваши диапазоны ввода и перегружает все обычные operator++ и operator*, которые вы знаете и любите от обычных итераторов. Затем iterator_range обертывает два из этих zip_iterator в пакет с помощью функции begin() и end(), которая позволяет использовать его в цикле цикла С++ 11. Он также обобщает более двух диапазонов ввода. Вы можете распаковать элемент K -th из кортежа с помощью функции-члена .get<K>.