2

I have an array std::array<T, N> arr for some T, N and I'd like to get an array of reference over arr's elements like so std::array<std::reference_wrapper<T>, N> arr_ref.

But as a reference needs to be set at its initialization, I did not work out a solution. Therefore I would like to do something like that:

std::array<std::reference_wrapper<T>, N> ref{}
for (std::size_t i{0}; i < N; ++i)
  ref[i] = arr[i];

But at compile-time and at the initialization of ref.

I thought of using some variadic template magic to convert my initial array to a parameter pack and then take a reference to each element but I am not sure this is possible.

My last option would be an array of raw ptrs or of std::optional<std::reference_wrapper<T>>.

5
  • 4
    Why do you need references to the individually elements, instead of having a reference to the actual array (as in auto& ref = arr;)? What is the actual and underlying problem your individual references is supposed to solve? Commented May 19, 2022 at 6:24
  • Feels like you are trying to create iterators, which already exist for arrays. Commented May 19, 2022 at 6:26
  • And there's also std::span Commented May 19, 2022 at 6:27
  • 1
    I have a generic custom Container<T> that internaly uses std::array<T, ...> and I would like to create a view over one with the same interface, e.g. create a Container<T&> ; Maybe this is a bad architecture Commented May 19, 2022 at 6:28
  • 2
    Then std::span (already mentioned, with Boost span as an alternative) might be useful. Or the ranges library (or the range library the standard ranges is based on). Commented May 19, 2022 at 6:31

1 Answer 1

3
#include <array>
#include <functional>
#include <utility>
#include <cstddef>

template<typename x_Item, ::std::size_t x_count, ::std::size_t... x_index_pack>
[[nodiscard]] auto wrap_impl
(
    ::std::array<x_Item, x_count> & items
,   ::std::index_sequence<x_index_pack...>
)
{
    return ::std::array<::std::reference_wrapper<x_Item>, x_count>{items[x_index_pack]...};
}

template<typename x_Item, ::std::size_t x_count>
[[nodiscard]] auto wrap
(
    ::std::array<x_Item, x_count> & items
)
{
    return wrap_impl(items, ::std::make_index_sequence<x_count>{});
}

#include <iostream>

int main()
{
    ::std::array items{1, 2, 3};
    auto wrapped_items{wrap(items)};
    for (auto & wrapped_item: wrapped_items)
    {
        ::std::cout << wrapped_item.get() << ::std::endl;
    }
    return 0;
}

online compiler

Sign up to request clarification or add additional context in comments.

1 Comment

Ow, I did not think of using an index_sequence! Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.