]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/lib/libk/union
update
[l4.git] / kernel / fiasco / src / lib / libk / union
1 // vi:ft=cpp
2 /*
3  * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
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.
9  *
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.
18  */
19
20 #pragma once
21
22 #include <type_traits>
23 #include <new>
24
25 namespace cxx {
26
27 template< typename BASE, typename ...IMPLS >
28 class Union
29 {
30   Union(Union const &) = delete;
31   Union &operator = (Union const &) = delete;
32
33 public:
34   Union() { construct<BASE>(); }
35
36   BASE *get()
37   { return reinterpret_cast<BASE*>(_d); }
38
39   BASE const *get() const
40   { return reinterpret_cast<BASE const*>(_d); }
41
42   BASE *operator -> () { return get(); }
43   BASE &operator * () { return *get(); }
44   BASE const *operator -> () const { return get(); }
45   BASE const &operator * () const { return *get(); }
46
47   template< typename T >
48   T *construct()
49   {
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;
53   }
54
55   template< typename T, typename ...ARGS >
56   T *construct(ARGS ...args)
57   {
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)...);
61   }
62
63   void destroy()
64   { get()->~BASE(); construct<BASE>(); }
65
66 private:
67   template< unsigned ...X >
68   struct Max;
69
70   template< unsigned Z >
71   struct Max<Z> { enum { value = Z }; };
72
73   template< unsigned X, unsigned Y >
74   struct Max<X,Y> { enum { value = X > Y ? X : Y }; };
75
76   template< unsigned X, unsigned ...Y >
77   struct Max<X, Y...> { enum { value = Max<X, Max<Y...>::value>::value }; };
78
79   enum
80   {
81     Size = Max<sizeof(BASE), sizeof(IMPLS)...>::value,
82     Words = (Size + sizeof(unsigned long) - 1) / sizeof(unsigned long)
83   };
84
85   unsigned long _d[Words];
86 };
87
88 }