Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / variant.hpp
1 #pragma once
2
3 /******************************************************************************
4 *
5 *   Copyright (c) 2019 AT&T Intellectual Property.
6 *   Copyright (c) 2018-2019 Nokia.
7 *
8 *   Licensed under the Apache License, Version 2.0 (the "License");
9 *   you may not use this file except in compliance with the License.
10 *   You may obtain a copy of the License at
11 *
12 *       http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *   Unless required by applicable law or agreed to in writing, software
15 *   distributed under the License is distributed on an "AS IS" BASIS,
16 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *   See the License for the specific language governing permissions and
18 *   limitations under the License.
19 *
20 ******************************************************************************/
21
22 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 #include <typeinfo>
24 #include <cassert>
25
26
27 // Local Includes: Application specific classes, functions, and libraries
28
29
30 namespace asn{
31
32 template<size_t S>
33 struct variant
34 {
35         typedef variant<S> self_type;
36         
37         template <typename T>
38         static void check_size () {static_assert(sizeof (T) <= S, "wrong type");}       
39         
40         variant ()
41         : typeinfo (nullptr)
42         {}
43         
44         template <typename T>
45         variant (const T& t)
46         : typeinfo (&typeid (T))
47         {
48                 check_size<T>();
49                 new (as_<T>()) T (t);
50         }
51
52         ~variant ()
53         {
54                 assert(!typeinfo);
55         }
56
57         template <typename T>
58         T& build ()
59         {
60                 assert(!typeinfo);
61                 typeinfo = & typeid (T);
62                 return *new (as_<T>()) T;
63         }
64     
65         template <typename T>
66         T& build (const T& t)
67         {
68                 assert(!typeinfo);
69                 check_size<T>();
70                 typeinfo = & typeid (T);
71                 return *new (as_<T> ()) T (t);
72         }
73
74         template <typename T>
75         T& as()
76         {
77                 assert(*typeinfo == typeid (T));
78                 check_size<T>();
79                 return *as_<T> ();
80         }
81         
82         template <typename T>
83         const T& as() const
84         {
85                 assert(*typeinfo == typeid (T));
86                 check_size<T>();
87                 return *as_<T> ();
88         }
89
90     template <typename T>
91     void swap(self_type& other)
92     {
93         assert (typeinfo);
94         assert (*typeinfo == *other.typeinfo);
95                 std::swap (as<T> (), other.as<T> ());
96     }
97
98     template <typename T>
99     void move(self_type& other)
100     {
101                 build<T> ();
102                 swap<T> (other);
103                 other.destroy<T> ();
104     }
105
106         template <typename T>
107         void copy(const self_type& other)
108         {
109                 build<T> (other.as<T> ());
110         }
111         
112         template <typename T>
113         void destroy()
114         {
115                 as<T> ().~T ();
116                 typeinfo = nullptr;
117         }
118
119 private:
120         self_type& operator=(const self_type&){}
121         variant (const self_type&){}
122         
123         template <typename T>
124         T* as_()
125         {
126                 void *p = buffer.raw;
127                 return static_cast<T*> (p);
128         }
129         
130         template <typename T>
131         const T* as_() const
132         {
133                 const void *p = buffer.raw;
134                 return static_cast<const T*> (p);
135         }
136   
137         union
138         {
139                 long double align_me;
140                 char raw[S];
141         } buffer;
142         
143         const std::type_info *typeinfo;
144 };
145
146 } //namspace asn