This code implements an unrestricted union which provides access by name and by index to any of its three members.
Since std::string
is non-trivially constructed and destroyed, I need to provide special constructor and destructor for the union
.
#include <iostream>
#include <string>
using namespace std ;
union MyUnion{
string parts[3] ;
struct{ string part1, part2, part3 ; } ;
MyUnion(){
new(parts+0) string ; //constructs the 3 strings in-place
new(parts+1) string ;
new(parts+2) string ;
}
~MyUnion(){
parts[0].~string() ; //calls string's destructor
parts[1].~string() ;
parts[2].~string() ;
}
} ;
int main(){
MyUnion u ;
u.part1 = "one" ; //access by name
u.part2 = "two" ;
u.part3 = "three" ;
cout << u.parts[0] << endl ; //access by index
cout << u.parts[1] << endl ;
cout << u.parts[2] << endl ;
}
This example compiles and works fine (seemingly), but my questions are:
string
's constructor throws an exception? Does that need to be caught so as to not try to destroy an object that was never constructed?The code compiles in VC2015, which does support unnamed structs. Please disregard that detail.
Is it safe to do this?
No. First, the common initial sequence rule only allows reading of members, not writing:
In a standard-layout union with an active member (9.3) of struct type
T1
, it is permitted to read a non-static data memberm
of another union member of struct typeT2
providedm
is part of the common initial sequence ofT1
andT2
; the behavior is as if the corresponding member ofT1
were nominated.
Secondly, common initial sequence is a trait of standard layout types:
The common initial sequence of two standard-layout struct (Clause 9) types is [...]
and std::string
is not required to be standard-layout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With