0

For example

using namespace std;

array<vector<int>, 3> a;
vector<int> v0, v1, v2;

// assign with move
a[0] = move(v0);
a[1] = move(v1);
a[2] = move(v2);

How to use one line to implement the assignment like a = {v0, v1, v2}?

user1899020
  • 11,941
  • 15
  • 66
  • 130
  • Did you try `a = array, 3>({v0, v1, v2})`? – πάντα ῥεῖ Dec 02 '16 at 05:20
  • `a = {v0, v1, v2}` actually works. – Rakete1111 Dec 02 '16 at 05:21
  • @Rakete1111 checked `a = {move(v0), move(v1), move(v2)};`. It works. Anyone can explain it? – user1899020 Dec 02 '16 at 05:29
  • @user1899020 [List initialization](http://en.cppreference.com/w/cpp/language/list_initialization) – Rakete1111 Dec 02 '16 at 05:39
  • "It" is a pronoun used to refer to a genderless.... Wait. No. Sorry. @user1899020, that works, but I don't think it does quite what you want it to do. It might be building a temp `vector` withthe moved `vector`s, then copying the temp `vector`. I'm going to hack out a test to see. – user4581301 Dec 02 '16 at 05:41
  • 3
    It's what I thought. `v0`..`v2` are moved into the initializer list, but the initializer list is copied into `a`. At least it is here: https://ideone.com/DH5GkI . Don't think you can `std::move` an initializer list. – user4581301 Dec 02 '16 at 05:59
  • 1
    Just to clarify: The objective is to have one line initialization and zero copies, yes? – user4581301 Dec 02 '16 at 06:27

3 Answers3

0

If you want to initialize a fresh std::array, array<vector<int>, 3> a = { move(v0), move(v1), move(v2) } would always work, otherwise construct a temporary std::array and then use std::move in <algorithm>:

array<unique_ptr<int>, 3> temp_arr = { move(a), move(b), move(c) };
move( begin(temp_arr), end(temp_arr), begin(arr) );
lz96
  • 2,401
  • 1
  • 22
  • 42
0

@user1899020 : You may refer to this What is std::move(), and when should it be used?

Please note "move semantics are performed transparently to the programmer. move its only a cast to pass a value from one point to another where the original lvalue will no longer be used."

So in below code:

a= {move(v0), move(v1), move(v2)};

for(int i=0; i <3; i++)
{
    // Iterate and print values of vector
    for(int n : a[i]) {
        std::cout << n << '\n';
    }
}

**//Code will NOT enter below for loop**
for (std::vector<int>::const_iterator  j= v0.begin(); j != v0.end(); j++)
    std::cout << *j << ' ';  

So if you want to use the retain the values in original vector,

  1. One ways is: a = {v0, v1, v2};
  2. another way could be using the pointers by initialising array as below:

    array<vector<int> *, 3> a = {&v0, &v1, &v2};
    
Community
  • 1
  • 1
Dipti Shiralkar
  • 312
  • 1
  • 5
0

Write a tuple_assign function:

template <class T>
using uncvref = std::remove_cv_t<std::remove_reference_t<T>>;

template <class T, class U, std::size_t...Is>
void tuple_assign_(T& to, U&& from, std::index_sequence<Is...>) {
    std::initializer_list<int>{
        (std::get<Is>(to) = std::get<Is>(std::forward<U>(from)), 0)...
    };
}

template <class T, class U,
    std::size_t TSize = std::tuple_size<uncvref<T>>::value,
    std::enable_if_t<TSize == std::tuple_size<uncvref<U>>::value, int*> = nullptr>
T& tuple_assign(T& to, U&& from) {
    tuple_assign_(to, std::forward<U>(from), std::make_index_sequence<TSize>{});
    return to;
}

and wrap the vectors with forward_as_tuple (DEMO):

tuple_assign(a, std::forward_as_tuple(std::move(v0), std::move(v1), std::move(v2)));
Casey
  • 38,510
  • 6
  • 83
  • 116