Guru Questions
-
The article [Manley02] cites the motivating case of writing a scripting language: Say that you want your language to support a single type for variables that at various times can hold an integer, a string, or a list. Creating a union { int i; list<int> l; string s; }; doesn't work for the reasons covered in Questions 1 and 2. The following code presents a workaround that attempts to support allowing any type to participate in a union. (For a more detailed explanation, see the original article.)
Critique this code and identify:
-
Mechanical errors, such as invalid syntax or nonportable conventions.
-
Stylistic improvements that would improve code clarity, reusability, and maintainability.
#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; }
-
-
Show a better way to achieve a generalized variant type, and comment on any tradeoffs you encounter.