4

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.

8
  • What does snmp have to do with this? Commented Oct 19, 2020 at 17:06
  • SNMP defines OIDs in this manner. Some code uses a MIB file. However, some code uses sequence definitions that are very repetitive that could be simplified if the sequence could be defined as a constant which depends on a shorter sequence. Commented Oct 19, 2020 at 17:08
  • 1
    I don't think there is a standard feature for this. But if you use std::array instead you could write one. The simple solution is to just use std::vector, though it has costs associated with dynamic allocation you may not have to pay here. Commented Oct 19, 2020 at 17:08
  • That's fine for motivation. But there is nothing snmp specific about this question, so I've removed the tag. Commented Oct 19, 2020 at 17:10
  • 1
    Can probably do it with a m*cro. Commented Oct 19, 2020 at 17:10

2 Answers 2

4

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)

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

Comments

0

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

Comments

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.