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:
- Is it safe to do this?
- Can I be sure that there will be no memory leaks?
- What if
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?
Note
The code compiles in VC2015, which does support unnamed structs. Please disregard that detail.
u.part1 = "one"
would be undefined behaviour. The active member isparts
, you are only allowed to access the active member – Brionu.part1 = "one" ;
is UB. You cannot access the non active member of a union. – Nichystd::string
to be standard layout. – Extremely&u.part1 < &u.part2
but doesn't require that&u.part1 + 1 == &u.part2
. A compiler might promise that. – Institute