Is there a way to count number of members in struct (ints in the below example) at compile time and define an array of same size in the same struct? Using a MACRO or a templated struct instead of the int type would be OK.
struct A
{
int myInts[numInts()]; // here numInts() == 2
int a;
char b;
char c;
int d;
char e;
};
I feel it may be possible with some constexpr hacks but haven't found a solution. What I need is to create an array where I can compact a copy of all the members to and the array needs to be statically allocated at compile time. Number of members will differ from a struct to struct, but the array should grow automatically to have space for all the members of interest. Also to make the matters worse, the array needs to be defined before the other members.
====== Edit
It seems there isn't a solution that does above without over-complicating struct design overall. Instead, I went with a need to specify array size manually.
This can be approched using MAP-MACRO and some templates.
You need to define your structs using a macro and pass all fields to it(eg. DEFINE_STRUCT(A, int a, char b, ...)
). The number of int
(or another type you want) fields can be counted by applying recursive template on a helper function of type void(int a, char b, ...)
. MAP-MACRO is needed for appending semicolons after each field.
#include <type_traits>
#include "map-macro/map.h" // https://github.com/swansontec/map-macro, we need the `MAP` macro
// Count how many arguments of Func are of type T
template<typename T, typename Func>
struct count_of_type;
template<typename T>
struct count_of_type<T, void()> { static constexpr std::size_t value = 0; };
template<typename T, typename FirstArg, typename...RestArgs>
struct count_of_type<T, void(FirstArg, RestArgs...)> {
static constexpr std::size_t value = std::is_same<T, FirstArg>::value + count_of_type<T, void(RestArgs...)>::value;
};
// Define your structs
#define APPEND_SEMICOLON(FIELD) FIELD;
#define DEFINE_STRUCT(NAME, FIELDS, ...) \
struct NAME { \
int myInts[count_of_type<int, void(FIELDS, ##__VA_ARGS__)>::value]; \
MAP(APPEND_SEMICOLON, FIELDS, ##__VA_ARGS__) \
};
DEFINE_STRUCT(A,
int a,
char b,
char c,
int d,
char e)
static_assert(std::is_same<decltype(A().myInts), int[2]>::value, "");