How to extend constant array in C++ using a base array

Viewed 125

In C++, is it possible to declare a constant array as an extension of a smaller constant array?

For example, if I have the following array:

const uint32 oid_base[] = {1,3,6,1,4,1,72000};
const uint32 oid_complete[] = {1,3,6,1,4,1,72000,1,1};

Is there a way to declare oid_complete using oid_base in the declaration of oid_complete?

My guess is that this is not possible in C++, but was wondering if someone had a good solution for this.

2 Answers

Isn't this what gsl::span is for?

const uint32_t oid_complete_data[] = {1,3,6,1,4,1,72000,1,1};

const gsl::span<const uint32_t> oid_complete{
  oid_complete_data,
  sizeof(oid_complete_data)};

const gsl::span<const uint32_t> oid_base{
  oid_complete_data,
  sizeof(oid_complete_data)-2};

(cf. https://godbolt.org/z/bGeGeP)

It's easy to do it with a for loop, but that requires that the element type is default-constructible. Not sure if you can do element-wise construction a la std::vector in constexpr C++20...

Anyway, you can always use index sequences. Please don't use a macro. I'm pretty sure there's a duplicate question somewhere by the way, with probably more elegant and general answers.

#include <array>
#include <iostream>
#include <utility>
#include <cstddef>

template<typename T, std::size_t... Is, typename... Extra>
constexpr auto extend_impl(std::array<T, sizeof...(Is)> const& base,
                           std::index_sequence<Is...>,
                           Extra&&... extra)
{
    return std::array{base[Is]..., std::forward<Extra>(extra)...};
}

template<typename T, std::size_t N, typename... Extra>
constexpr auto extend(std::array<T, N> const& base, Extra&&... extra)
{
    return extend_impl(base, std::make_index_sequence<N>{},
                       std::forward<Extra>(extra)...);
}

constexpr std::array base = {1, 2, 3};
constexpr std::array extended = extend(base, 4, 5, 6);

int main()
{
    for(auto e : extended)
        std::cout << e << " ";
}

On Godbolt

Related