I want to declare some constant arrays which have some shared part, currently I have to use macros to achieve this.
I want:
struct Param{int a; int b;};
const static std::vector<Param> SHARED_DATA = {
{1,2},
{3,4},
};
const static std::vector<Param> TEST_DATA_ONE = {
{5,6},
SHARED_DATA,
{7,8},
};
const static std::vector<Param> TEST_DATA_TWO = {
{9,10},
SHARED_DATA,
{11,12},
};
Obviously the above code can not compile.
What I'm using now:
#define SHARED_DATA \
{1,2}, \
{3,4}
#define TEST_DATA_ONE \
{5,6}, \
SHARED_DATA, \
{7,8} \
#define TEST_DATA_TWO \
{9,10}, \
SHARED_DATA, \
{11,12} \
const Param PACK_DATA_ONE[] = {
TEST_DATA_ONE,
{1,2},
};
const Param PACK_DATA_TWO[] = {
TEST_DATA_TWO,
{1,2},
};
Is there any C/C++ way for concatenating constant arrays other than macro?
std::vector is more of a runtime thing so you could make runtime functions for concatenating. However if you use std::array then you can combine at compile time.
#include <array>
#include <type_traits>
// Compile time function to add one value to an array
template<typename type_t, std::size_t N>
static constexpr void append(std::array<type_t, N>& arr, type_t& value, std::size_t& offset)
{
arr[offset] = value;
offset++;
}
// Compile time function to add another array to the array
template<typename type_t, std::size_t N, std::size_t M>
static constexpr void append(std::array<type_t, N>& arr, const std::array<type_t,M>& values, std::size_t& offset)
{
for (std::size_t n = 0; n < values.size(); ++n, ++offset)
{
arr[offset] = values[n];
}
}
// Create a variadic template function to build an array
// from a mix of values and other arrays
template<typename type_t, typename... args_t>
static constexpr auto build_array(args_t&&... args)
{
// calculate the size of the final array by summing
// the sizes of the arguments divided by the size of the underlying type
const auto size_v = ((sizeof(args_t)/sizeof(type_t)) + ...);
std::array<type_t, size_v> values{};
// start adding values at the start of the array
std::size_t offset{0ul};
// the compiler will select the correct append function to use at compile time
// what you see here is a fold expression and it will "loop" over all args
(append(values, args, offset),...);
return values;
}
int main()
{
constexpr std::array arr1{ 2, 3 };
constexpr std::array arr2{ 5, 6 };
constexpr auto arr3 = build_array<int>(1, arr1, 4, arr2, 7);
static_assert(arr3.size() == 7);
static_assert(arr3[0] == 1);
static_assert(arr3[1] == 2);
static_assert(arr3[2] == 3);
static_assert(arr3[3] == 4);
static_assert(arr3[4] == 5);
static_assert(arr3[5] == 6);
static_assert(arr3[6] == 7);
return 0;
}