4

I want to copy an array using range for. Is it possible?

Something like (obviously not working)

unsigned arr[15] = {};
unsigned arr2[15];

for (auto i : arr, auto &j : arr2)
    j = i;

Or are there some other tricks to avoid operating the size of arrays, if I know for sure they are of the same lenght?

UPD I really like the @PavelDavydov solution. But could anyone please offer a standard lib only solution. C++11 contains pairs and tuples too.

for (auto pair : std::make_tuple(&arr, &arr2));
NuPagadi
  • 1,410
  • 1
  • 11
  • 31

4 Answers4

10
#include <boost/range/combine.hpp>

for (const auto& pair : boost::combine(arr, arr2)) {
  cout << get<0>(pair) << endl;
}

Update: ok, if you want to do it without boost, you can implement a higher order function for that.

template <class T, unsigned long FirstLen, unsigned long SecondLen, class Pred> 
typename std::enable_if<FirstLen == SecondLen, void>::type loop_two(T (&first)[FirstLen], T (&second)[SecondLen], Pred pred) {
  for (unsigned long len = 0; len < FirstLen; ++len) {
    pred(first[len], second[len]);  
  }
}

and than use it like this:

loop_two(arr, arr1, [] (unsigned a, unsigned b) {
  cout << a << endl;
});
Pavel Davydov
  • 3,379
  • 3
  • 28
  • 41
  • Is it possible with standard lib? C++11 includes pairs. I tried by myself but no luck. – NuPagadi Mar 10 '14 at 11:41
  • Can you please give a link to the documentation of `boost::combine`? – Ralph Tandetzky Mar 10 '14 at 11:47
  • @RalphTandetzky, http://www.boost.org/doc/libs/1_46_1/boost/range/combine.hpp – NuPagadi Mar 10 '14 at 11:50
  • @user2198121 I did not mean a link to the header file and implementation, but a link to documentation, which tells me, what the thing is supposed to do, preconditions, postconditions, effects, etc. – Ralph Tandetzky Mar 10 '14 at 11:55
  • @user2198121 I named a variable 'pair' here, but in fact it's a tuples::cons. c++11 doesn't have any similar functions, AFAIK, unfortunately. Be careful however, combine produce undefined behavior if ranges are not equal. – Pavel Davydov Mar 10 '14 at 11:55
  • @RalphTandetzky boost::combine is an undocumented feature. – Pavel Davydov Mar 10 '14 at 11:56
  • @PavelDavydov, but C++11 has tuples too. Or C++11 tuples strongly != Boost tuples? – NuPagadi Mar 10 '14 at 12:00
  • If `boost::combine` is not documented, can we rely on it then? There's no guarantee that future boost releases try to maintain the current behavior. That gives me a bad gut feel about this solution. :S – Ralph Tandetzky Mar 10 '14 at 12:05
  • @RalphTandetzky the documentation will soon be fixed - see https://svn.boost.org/trac/boost/ticket/8028 – Pavel Davydov Mar 10 '14 at 12:49
  • @PavelDavydov, thanks! It's a pity, there is no solution for `range for` though. – NuPagadi Mar 10 '14 at 12:51
  • @user2198121 yeah, it would be nice if someone add this feature to c++17... Another option we have is just to switch to [d language](http://dlang.org/phobos/std_range.html#zip). :) – Pavel Davydov Mar 10 '14 at 13:00
  • @PavelDavydov, yeah, tovarisch! C++17 will be a Revolution! Lenin, Partiya, Digital October! – NuPagadi Mar 10 '14 at 13:40
5
#include <iterator>
//.. 

unsigned arr[15] = {};
unsigned arr2[15];

//.. 

auto it = std::begin( arr2 );

for ( unsigned x : arr ) *it++ = x;

It would be better to use standard algorithm std::copy because its name says about your intention.

#include <algorithm>
#include <iterator>
//...

std::copy( std::begin( arr ), std::end( arr ), std::begin( arr2 ) );

For arrays of arithmetic types you can use also C function memcpy

#include <cstring>

...

std::memcpy( arr2, arr, std::extent<decltype(arr)>::value * sizeof( unsigned ) );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
3

There are several good answers already, another is to use a zip iterator such as https://gitlab.com/redistd/redistd/blob/master/include/redi/zip.h (which currently depends on Boost.Tuple)

#include <redi/zip.h>

int main()
{
  unsigned arr[15] = {};
  unsigned arr2[15];

  for (auto i : redi::zip(arr, arr2))
    i.get<1>() = i.get<0>();
}
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
1

It's possible. I suggest use std::begin and std::end function. For example:

for(auto it1 = std::begin(arr), it2 = std::begin(arr2); it1 != std::end(arr); ++it1,++it2)
 *it2 = *it1;

However, you can use std:array or std::vector instead 'normal' arrays. It's C++11!

Tacet
  • 1,411
  • 2
  • 17
  • 32