3 * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>
4 * economic rights: Technische Universität Dresden (Germany)
6 * This file is part of TUD:OS and distributed under the terms of the
7 * GNU General Public License 2.
8 * Please see the COPYING-GPL-2 file for details.
10 * As a special exception, you may use this file as part of a free software
11 * library without restriction. Specifically, if other files instantiate
12 * templates or use macros or inline functions from this file, or you compile
13 * this file and link it with other files to produce an executable, this
14 * file does not by itself cause the resulting executable to be covered by
15 * the GNU General Public License. This exception does not however
16 * invalidate any other reasons why the executable file might be covered by
17 * the GNU General Public License.
22 #include <type_traits>
27 template< typename BASE, typename ...IMPLS >
30 Union(Union const &) = delete;
31 Union &operator = (Union const &) = delete;
34 Union() { construct<BASE>(); }
37 { return reinterpret_cast<BASE*>(_d); }
39 BASE const *get() const
40 { return reinterpret_cast<BASE const*>(_d); }
42 BASE *operator -> () { return get(); }
43 BASE &operator * () { return *get(); }
44 BASE const *operator -> () const { return get(); }
45 BASE const &operator * () const { return *get(); }
47 template< typename T >
50 BASE *test = reinterpret_cast<T*>(10); (void)test;
51 static_assert(sizeof(T) <= sizeof(_d), "dynamic type of union too big");
52 return new ((void*)_d) T;
55 template< typename T, typename ...ARGS >
56 T *construct(ARGS ...args)
58 BASE *test = reinterpret_cast<T*>(10); (void)test;
59 static_assert(sizeof(T) <= sizeof(_d), "dynamic type of union too big");
60 return new ((void*)_d) T(cxx::forward<ARGS>(args)...);
64 { get()->~BASE(); construct<BASE>(); }
67 template< unsigned ...X >
70 template< unsigned Z >
71 struct Max<Z> { enum { value = Z }; };
73 template< unsigned X, unsigned Y >
74 struct Max<X,Y> { enum { value = X > Y ? X : Y }; };
76 template< unsigned X, unsigned ...Y >
77 struct Max<X, Y...> { enum { value = Max<X, Max<Y...>::value>::value }; };
81 Size = Max<sizeof(BASE), sizeof(IMPLS)...>::value,
82 Words = (Size + sizeof(unsigned long) - 1) / sizeof(unsigned long)
85 unsigned long _d[Words];