简体   繁体   English

您可以为具有 const 成员的联合编写一个复制构造函数吗?

[英]Can you write a copy constructor for a union with const members?

Suppose I have a struct that contains a union with const members, like so:假设我有一个包含const成员联合的结构,如下所示:

struct S
{
  // Members

  const enum { NUM, STR } type;

  union
  {
    const int a;
    const std::string s;
  };

  // Constructors

  S(int t_a) : type(NUM), a(t_a);

  S(const std::string & t_s) : type(STR), s(t_s);

};

So far, so good.到现在为止还挺好。 But now say I want to write a copy-constructor for this type.但是现在说我想为这种类型编写一个复制构造函数。

It doesn't seem like this involves doing anything nefarious, but since I need to initialize the const members in member initializers I don't see how to do this based on logic that depends on the type member.这似乎并不涉及做任何邪恶的事情,但是由于我需要在成员初始值设定项中初始化 const 成员,因此我不知道如何根据取决于type成员的逻辑来执行此操作。

Questions:问题:

  • Is it possible to write this constructor?是否可以编写此构造函数?

  • If not, is this essentially a syntactic oversight, or is there some fundamental reason that the language can't support such a thing?如果不是,这本质上是一种语法上的疏忽,还是存在某种语言不能支持这样的事情的根本原因?

Yes, it is possible to write copy constructor here.是的,可以在这里编写复制构造函数。 Actually it is already done inside std::variant implementation, which shall support const -types among others.实际上它已经在std::variant实现中完成,它应该支持const类型等。 So your class S can be replaced with所以你的类S可以替换为

using S = std::variant<const int, const std::string>;

But if for dome reason you cannot use std::variant then copy-constructor can be written using std::construct_at function as follows:但是,如果由于圆顶原因您不能使用std::variant则可以使用std::construct_at函数编写复制std::construct_at函数,如下所示:

#include <string>

struct S {
  const enum { NUM, STR } type;

  union {
    const int a;
    const std::string s;
  };

  S(int t_a) : type(NUM), a(t_a) {}
  S(const std::string & t_s) : type(STR), s(t_s) {}
  S(const S & rhs) : type(rhs.type) {
      if ( type == NUM ) std::construct_at( &a, rhs.a );
      if ( type == STR ) std::construct_at( &s, rhs.s );
  }
  ~S() {
      if ( type == STR ) s.~basic_string();
  }
};

int main() {
    S s(1);
    S u = s;

    S v("abc");
    S w = v;
}

Demo: https://gcc.godbolt.org/z/TPe8onhWs演示: https : //gcc.godbolt.org/z/TPe8onhWs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM