Listing 1: A working example of the idiom

#include "stdafx.h"
#pragma warning( disable : 4786 )  
#include <list>
#include <string>
#include <iostream>
using namespace std;

#define max(a,b) (a)>(b)?(a):(b)

typedef list<int> LIST;
typedef string STRING;

struct MYUNION {
    MYUNION() : currtype( NONE ) {}
    ~MYUNION() {cleanup();}

    enum uniontype {NONE,_INT,_LIST,_STRING}; 
    uniontype currtype; 

    inline int& getint();
    inline LIST& getlist();
    inline STRING& getstring();

protected:
    union {
        int i;
        unsigned char buff[max(sizeof(LIST),sizeof(STRING))];
    } U; 
    
    void cleanup();
}; 

inline int& MYUNION::getint()
{
    if( currtype==_INT ) {
        return U.i;
    } else {
        cleanup();
        currtype=_INT;
        return U.i; 
    } // else
}

inline LIST& MYUNION::getlist()
{
    if( currtype==_LIST ) {
        return *(reinterpret_cast<LIST*>(U.buff));
    } else {
        cleanup();
        LIST* ptype = new(U.buff) LIST();
        currtype=_LIST; 
        return *ptype; 
    } // else
}

inline STRING& MYUNION::getstring()
{
    if( currtype==_STRING) {
        return *(reinterpret_cast<STRING*>(U.buff));
    } else {
        cleanup();
        STRING* ptype = new(U.buff) STRING();
        currtype=_STRING; 
        return *ptype; 
    } // else
}

void MYUNION::cleanup()
{
    switch( currtype ) {
        case _LIST: {
            LIST& ptype = getlist();
            ptype.~LIST();
            break; 
        } // case
        case _STRING: {
            STRING& ptype = getstring();
            ptype.~STRING();
            break;
        } // case
        default: break;
    } // switch
    currtype=NONE;
}

int main(int argc, char* argv[])
{
    cout << "sizeof(int)="       << sizeof(int)     << endl;
    cout << "sizeof(LIST)="    << sizeof(LIST)    << endl;
    cout << "sizeof(STRING)="  << sizeof(STRING)  << endl;
    cout << "sizeof(MYUNION)=" << sizeof(MYUNION) << endl;

    MYUNION u; 

    // access union as integer
    u.getint() = 12345;
    cout << "int=" << u.getint() << endl;

    // access union as std::list
    LIST& list = u.getlist();
    list.push_back(5);
    list.push_back(10);
    list.push_back(15);

    LIST::iterator it = list.begin();
    while( it != list.end() ) {
        cout << "list item=" << *(it) << endl;
        it++; 
    } // while

    // access union as std::string
    STRING& str = u.getstring();
    str = "Hello world!";

    cout << "string='" << str.c_str() << "'" << endl;

    return 0;
}
— End of Listing —