编译时:计算 X 类型成员的 #(~N) 并定义一个成员数组 [N]?

Compile-time: count #(~N) of members of type X and define a member array[N]?

有没有办法在编译时计算结构中的成员数量(下例中的整数),并在同一个结构中定义一个相同大小的数组?使用 MACRO 或模板化结构而不是 int 类型就可以了。

struct A
{
    int myInts[numInts()];  // here numInts() == 2
    int a;
    char b;
    char c;
    int d;
    char e;
};

我觉得使用一些 constexpr hack 可能是可行的,但还没有找到解决方案。我需要的是创建一个数组,我可以在其中压缩所有成员的副本,并且需要在编译时静态分配该数组。成员数量因结构而异,但数组应自动增长为所有感兴趣的成员都具有 space。更糟糕的是,数组需要在其他成员之前定义。

====== 编辑

似乎没有一种解决方案可以在不使结构设计整体过于复杂的情况下实现上述功能。相反,我需要手动指定数组大小。

某些类型可以使用 magic_get library。限制是:

T must be constexpr aggregate initializable and must not contain references nor bitfields

你的post中的结构体A满足这个条件。

magic_get 使用聚合初始化检测 non-static 数据成员的数量。基本上,这个想法是,如果您有某种类型 U 可以转换为任何其他类型,那么当 U() 的数量等于数量时,T{U(), U(), ..., U()} 将是 well-formed聚合中的元素数 T。 (如果 T 有一些成员有默认的成员初始化器或者可以是 value-initialized,当初始化器比元素少时,这个表达式也可能是 well-formed,所以你必须取最大有效的数字。)并且 SFINAE 可用于检测这样的表达式是否为 well-formed。

您可以在 fields_count.hpp

中查看所有血淋淋的细节

这可以使用 MAP-MACRO 和一些模板来解决。 您需要使用宏定义结构并将所有字段传递给它(例如 DEFINE_STRUCT(A, int a, char b, ...))。 int(或您想要的其他类型)字段的数量可以通过在类型 void(int a, char b, ...) 的辅助函数上应用递归模板来计算。 MAP-MACRO 需要在每个字段后附加分号。

#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, "");