c – 访问命名联合中的字段

前端之家收集整理的这篇文章主要介绍了c – 访问命名联合中的字段前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我希望在以下结构中有一个命名联合,这样我就可以在不知道哪个字段是“活动”的情况下记忆它.
struct Literal {
  enum class Type : size_t {
    INT = 1,LONG,FLOAT,DOUBLE
  } type;

  union {
    int li;
    long ll;
    float lf;
    double ld;
  } v;

  constexpr Literal(int li): type{Type::INT},v.li{li} {}
  constexpr Literal(long ll): type{Type::LONG},v.ll{ll} {}
  constexpr Literal(float lf): type{Type::FLOAT},v.lf{lf} {}
  constexpr Literal(double ld): type{Type::DOUBLE},v.ld{ld} {}
};

如何初始化构造函数中的字段? v.li {li}和li {li}都没有工作.

我也试过v {li},但它只适用于第一个构造函数,因为它将另外3个构建器转换为int.

编辑:来自@StoryTeller的回答和评论

struct Literal {
  enum class Type : size_t {
    INT = 1,DOUBLE
  } type;
  union {
    #define UNION_FIELDS int li; long ll; float lf; double ld;
    union { UNION_FIELDS } value;
    union { UNION_FIELDS };
  };
};

解决方法

您只能在其c’tors成员初始化列表中初始化Literal的直接成员.由于缩小了转换次数,联合成员的聚合初始化将不起作用.所以你的选择是:

>命名联合成员类型,并为其添加适当的c’tors.
>递归以强制将union字段视为Literal类的字段.有一个工会联盟,并依靠共同的初始序列保证:

union {
  union {
      int li;
      long ll;
      float lf;
      double ld;
  } v;
  union {
      int li;
      long ll;
      float lf;
      double ld;
  };
};

constexpr Literal(int li): type{Type::INT},li{li} {}
constexpr Literal(long ll): type{Type::LONG},ll{ll} {}
constexpr Literal(float lf): type{Type::FLOAT},lf{lf} {}
constexpr Literal(double ld): type{Type::DOUBLE},ld{ld} {}

以上允许您通过名称引用每个字段,由于匿名联合成员,以及使用命名的v成员将它们混合在一起.但我会第一个承认,这很难看.

猜你在找的C&C++相关文章