My reading of the standard is that std::memcpy
is safe whenever the type is trivially copyable.
From 9 Classes, we can see that union
s are class types and so trivially copyable applies to them.
A union is a class defined with the class-key union; it holds only one data member at a time (9.5).
A trivially copyable class is a class that:
- has no non-trivial copy constructors (12.8),
- has no non-trivial move constructors (12.8),
- has no non-trivial copy assignment operators (13.5.3, 12.8),
- has no non-trivial move assignment operators (13.5.3, 12.8), and
- has a trivial destructor (12.4).
The exact meaning of trivially copyable is given in 3.9 Types:
For any object (other than a base-class subobject) of trivially copyable type
T
, whether or not the object holds a valid value of typeT
, the underlying bytes (1.7) making up the object can be copied into an array ofchar
orunsigned char
. If the content of the array ofchar
orunsigned char
is copied back into the object, the object shall subsequently hold its original value.For any trivially copyable type
T
, if two pointers toT
point to distinctT
objectsobj1
andobj2
, where neitherobj1
norobj2
is a base-class subobject, if the underlying bytes (1.7) making upobj1
are copied intoobj2
,obj2
shall subsequently hold the same value asobj1
.
The standard also gives an explicit example of both.
So, if you were copying the entire union, the answer would be unequivocally yes, the active member will be “copied” along with the data. (This is relevant because it indicates that std::memcpy
must be regarded as a valid means of changing the active element of a union, since using it is explicitly allowed for whole union copying.)
Now, you are instead copying into a member of the union. The standard doesn’t appear to require any particular method of assigning to a union member (and hence making it active). All it does is specify (9.5) that
[ Note: In general, one must use explicit destructor class and placement new operators to change the active member of a union. — end note]
which it says, of course, because C++11 allows objects of non-trivial type in unions. Note the “in general” on the front, which quite clearly indicates that other methods of changing the active member are permissible in specific cases; we already know this to be the case because assignment is clearly permitted. Certainly there is no prohibition on using std::memcpy
, where its use would otherwise be valid.
So my answer is yes, this is safe, and yes, it changes the active member.