Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Union member has a non-trivial copy constructor [duplicate]

I have a union that looks like this:

union {
  int intValue;
  double doubleValue;
  std::string stringValue;
  void *pointerValue;
} values;

When I compile it, I get this error message (yes, I did #include <string>):

./Value.hh:19:19: error: union member 'stringValue' has a non-trivial copy constructor                 
      std::string stringValue;                                                                         
                  ^                                                                                    
/Developer/SDKs/MacOSX10.7.sdk//usr/include/c++/4.2.1/bits/basic_string.h:434:7: note: because         
      type 'std::basic_string<char>' has a user-declared copy constructor                              
      basic_string(const basic_string& __str);                                                         
      ^

I compile it using this command:

$ clang++ *.cc -isysroot /Developer/SDKs/MacOSX10.7.sdk/ -shared

How can I use an std::string in a union?


1 Answers

You cannot.

A union combines two pieces of functionality: the ability to store an object which may be of a select number of types, and the ability to effectively (and implementation-defined) convert between those types. You could put an integer in and look at its representation as a double. And so forth.

Because a union must support both of these pieces of functionality (and for a few other reasons, like being able to construct one), a union prevents you from doing certain things. Namely, you cannot put "live" objects in them. Any object that is "living" enough that it needs a non-default copy constructor (among many other restrictions) cannot be a member of a union.

After all, a union object does not really have the concept of which type of data it actually stores. It does not store one type of data; it stores all of them, at the same time. It is up to you to be able to fish the right type out. So how could it reasonably copy one union value into another?

Members of a union must be a POD (plain-old-data) type. And while C++11 does loosen those rules, objects still must have a default (or otherwise trivial) copy constructor. And std::string's copy constructor is non-trivial.

What you likely want is a boost::variant. That is an object that can store a number of possible types, just like a union. Unlike a union however, it is type-safe. It therefore knows what is actually in the union; it is therefore able to copy itself and otherwise behave like a regular C++ object.

like image 66
Nicol Bolas Avatar answered Sep 14 '25 16:09

Nicol Bolas