
On 09/17/10 10:11, dherring@ll.mit.edu wrote:
Hi,
While C++0x promises to change things (see draft spec section 9.5), C++ currently does not allow unions to contain members having a nontrivial constructor, operator=, or destructor. This excludes std::string, std::complex, structures containing either, etc.
The "standard" workaround is to allocate your own memory and use manual type casting. Boost::aligned_storage can be used to maintain proper alignment, but it cannot be placed inside a union due to the default ctor, dtor, and noncopyable functions. Thus I am forced to use part of boost::detail.
Here is a simple example.
#include <boost/type_traits/aligned_storage.hpp>
// define a union-safe wrapper template <class T> struct UnWrap { boost::detail::aligned_storage::aligned_storage_imp< sizeof(T), boost::alignment_of<T>::value> space;
T * get() const { return static_cast<T *>(space.address()); } T * operator->() const { return get(); } T & operator*() const { return *get(); } };
union U { UnWrap<std::string> s; int x; };
U u; new (u.s.get()) std::string; *u.s="hi";
Questions: - Is there a better way to do this? - Am I doing something blatantly wrong? - Could aligned_storage_impl be exposed for such uses? (AIUI, the detail namespace contains unsupported internals.)
Thanks, Daniel
Hi Daniel, Why not use boost::variant<std::string,int>? Using your example: boost::variant<std::string,int> u; u = "hi"; assert(u.which()==1); u = 9; assert(u.which()==2); (I may have the which results off by one, but you get the idea). -regards, Larry