Доступ к полям в именованном объединении

Я хочу иметь именованное объединение в следующей структуре, чтобы я мог memcpy, не зная, какое поле является «активным».

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,
    LONG,
    FLOAT,
    DOUBLE
  } type;
  union {
    #define UNION_FIELDS int li; long ll; float lf; double ld;
    union { UNION_FIELDS } value;
    union { UNION_FIELDS };
  };
};
7 голосов | спросил DBLouis 31 +03002017-10-31T12:37:10+03:00312017bEurope/MoscowTue, 31 Oct 2017 12:37:10 +0300 2017, 12:37:10

1 ответ


0

Вы можете инициализировать только прямых членов Literal в его списке инициализаторов членов c'tors. Совокупная инициализация члена объединения не будет работать из-за сужения конверсий. Итак, вы можете:

  1. Назовите тип члена объединения и добавьте в него соответствующие символы.
  2. Рекурсировать, чтобы принудительно обрабатывать поля объединения как поля класса 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 участник. Но я буду первым, чтобы признать, это некрасиво.

ответил StoryTeller 31 +03002017-10-31T12:48:11+03:00312017bEurope/MoscowTue, 31 Oct 2017 12:48:11 +0300 2017, 12:48:11

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132