Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unpacking a std::array

Tags:

c++

c++11

stl

I tried to unpack a std::array via std::tie:

#include <tuple>
#include <array>

int main() {
    std::array<int, 3> arr = {1, 2, 3};
    int a, b, c;
    std::tie(a, b, c) = arr;
    return 0;
}

This works in clang, but fails to compile in g++ 5.4: no match for ‘operator=’. Compile options are -std=c++11.

  1. Why does this work in clang but not g++?
  2. How can I portably unpack a std::array, like one might unpack a tuple?

Thanks for any help!

like image 910
ridiculous_fish Avatar asked Dec 04 '16 06:12

ridiculous_fish


1 Answers

I would create dedicated function to transform array to tuple. C++14 code could look as follows:

template <class T, std::size_t N, std::size_t... Is>
auto unpack_impl(std::array<T, N> &arr, index_sequence<Is...>) -> decltype(std::make_tuple(arr[Is]...)) {
    return std::make_tuple( arr[Is]... );
}

template <class T, std::size_t N>
auto unpack(std::array<T, N> &arr) -> decltype(unpack_impl(arr, make_index_sequence<N>{})) {
    return unpack_impl(arr, make_index_sequence<N>{});
}

And then use it like:

std::array<int, 3> arr = {{1, 2, 3}};
int a, b, c;
std::tie(a, b, c) = unpack(arr);

In c++11 you would need however to implement integer_sequence as it does not come out of the box in the standard...

Here you can find complete c++11 solution.

Edit:

If an array contains some more complex objects you might want to avoid unnecessary copy. To do that instead of make_tuple you may use tuple of const references or if the constness doesn't bother you you could simple tie array elements up:

template <class T, std::size_t N, std::size_t... Is>
auto unpack_impl(std::array<T, N> &arr, index_sequence<Is...>) -> decltype(std::tie( arr[Is]... )) {
    return std::tie( arr[Is]... );
}

Edit2:

This one compiles also on VS

like image 94
W.F. Avatar answered Oct 25 '22 03:10

W.F.