jpayne@69
|
1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
jpayne@69
|
2 // Licensed under the MIT License:
|
jpayne@69
|
3 //
|
jpayne@69
|
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
jpayne@69
|
5 // of this software and associated documentation files (the "Software"), to deal
|
jpayne@69
|
6 // in the Software without restriction, including without limitation the rights
|
jpayne@69
|
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
jpayne@69
|
8 // copies of the Software, and to permit persons to whom the Software is
|
jpayne@69
|
9 // furnished to do so, subject to the following conditions:
|
jpayne@69
|
10 //
|
jpayne@69
|
11 // The above copyright notice and this permission notice shall be included in
|
jpayne@69
|
12 // all copies or substantial portions of the Software.
|
jpayne@69
|
13 //
|
jpayne@69
|
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
jpayne@69
|
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
jpayne@69
|
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
jpayne@69
|
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
jpayne@69
|
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
jpayne@69
|
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
jpayne@69
|
20 // THE SOFTWARE.
|
jpayne@69
|
21
|
jpayne@69
|
22 #pragma once
|
jpayne@69
|
23
|
jpayne@69
|
24 #include "common.h"
|
jpayne@69
|
25
|
jpayne@69
|
26 KJ_BEGIN_HEADER
|
jpayne@69
|
27
|
jpayne@69
|
28 namespace kj {
|
jpayne@69
|
29
|
jpayne@69
|
30 namespace _ { // private
|
jpayne@69
|
31
|
jpayne@69
|
32 template <uint i, template<uint> class Fail, typename Key, typename... Variants>
|
jpayne@69
|
33 struct TypeIndex_;
|
jpayne@69
|
34 template <uint i, template<uint> class Fail, typename Key, typename First, typename... Rest>
|
jpayne@69
|
35 struct TypeIndex_<i, Fail, Key, First, Rest...> {
|
jpayne@69
|
36 static constexpr uint value = TypeIndex_<i + 1, Fail, Key, Rest...>::value;
|
jpayne@69
|
37 };
|
jpayne@69
|
38 template <uint i, template<uint> class Fail, typename Key, typename... Rest>
|
jpayne@69
|
39 struct TypeIndex_<i, Fail, Key, Key, Rest...> { static constexpr uint value = i; };
|
jpayne@69
|
40 template <uint i, template<uint> class Fail, typename Key>
|
jpayne@69
|
41 struct TypeIndex_<i, Fail, Key>: public Fail<i> {};
|
jpayne@69
|
42
|
jpayne@69
|
43 template <uint i>
|
jpayne@69
|
44 struct OneOfFailError_ {
|
jpayne@69
|
45 static_assert(i == -1, "type does not match any in OneOf");
|
jpayne@69
|
46 };
|
jpayne@69
|
47 template <uint i>
|
jpayne@69
|
48 struct OneOfFailZero_ {
|
jpayne@69
|
49 static constexpr int value = 0;
|
jpayne@69
|
50 };
|
jpayne@69
|
51
|
jpayne@69
|
52 template <uint i>
|
jpayne@69
|
53 struct SuccessIfNotZero {
|
jpayne@69
|
54 typedef int Success;
|
jpayne@69
|
55 };
|
jpayne@69
|
56 template <>
|
jpayne@69
|
57 struct SuccessIfNotZero<0> {};
|
jpayne@69
|
58
|
jpayne@69
|
59 enum class Variants0 {};
|
jpayne@69
|
60 enum class Variants1 { _variant0 };
|
jpayne@69
|
61 enum class Variants2 { _variant0, _variant1 };
|
jpayne@69
|
62 enum class Variants3 { _variant0, _variant1, _variant2 };
|
jpayne@69
|
63 enum class Variants4 { _variant0, _variant1, _variant2, _variant3 };
|
jpayne@69
|
64 enum class Variants5 { _variant0, _variant1, _variant2, _variant3, _variant4 };
|
jpayne@69
|
65 enum class Variants6 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5 };
|
jpayne@69
|
66 enum class Variants7 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6 };
|
jpayne@69
|
67 enum class Variants8 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
68 _variant7 };
|
jpayne@69
|
69 enum class Variants9 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
70 _variant7, _variant8 };
|
jpayne@69
|
71 enum class Variants10 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
72 _variant7, _variant8, _variant9 };
|
jpayne@69
|
73 enum class Variants11 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
74 _variant7, _variant8, _variant9, _variant10 };
|
jpayne@69
|
75 enum class Variants12 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
76 _variant7, _variant8, _variant9, _variant10, _variant11 };
|
jpayne@69
|
77 enum class Variants13 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
78 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12 };
|
jpayne@69
|
79 enum class Variants14 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
80 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
81 _variant13 };
|
jpayne@69
|
82 enum class Variants15 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
83 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
84 _variant13, _variant14 };
|
jpayne@69
|
85 enum class Variants16 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
86 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
87 _variant13, _variant14, _variant15 };
|
jpayne@69
|
88 enum class Variants17 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
89 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
90 _variant13, _variant14, _variant15, _variant16 };
|
jpayne@69
|
91 enum class Variants18 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
92 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
93 _variant13, _variant14, _variant15, _variant16, _variant17 };
|
jpayne@69
|
94 enum class Variants19 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
95 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
96 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18 };
|
jpayne@69
|
97 enum class Variants20 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
98 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
99 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
100 _variant19 };
|
jpayne@69
|
101 enum class Variants21 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
102 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
103 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
104 _variant19, _variant20 };
|
jpayne@69
|
105 enum class Variants22 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
106 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
107 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
108 _variant19, _variant20, _variant21 };
|
jpayne@69
|
109 enum class Variants23 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
110 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
111 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
112 _variant19, _variant20, _variant21, _variant22 };
|
jpayne@69
|
113 enum class Variants24 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
114 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
115 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
116 _variant19, _variant20, _variant21, _variant22, _variant23 };
|
jpayne@69
|
117 enum class Variants25 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
118 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
119 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
120 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24 };
|
jpayne@69
|
121 enum class Variants26 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
122 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
123 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
124 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
125 _variant25 };
|
jpayne@69
|
126 enum class Variants27 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
127 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
128 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
129 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
130 _variant25, _variant26 };
|
jpayne@69
|
131 enum class Variants28 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
132 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
133 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
134 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
135 _variant25, _variant26, _variant27 };
|
jpayne@69
|
136 enum class Variants29 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
137 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
138 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
139 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
140 _variant25, _variant26, _variant27, _variant28 };
|
jpayne@69
|
141 enum class Variants30 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
142 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
143 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
144 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
145 _variant25, _variant26, _variant27, _variant28, _variant29 };
|
jpayne@69
|
146 enum class Variants31 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
147 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
148 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
149 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
150 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30 };
|
jpayne@69
|
151 enum class Variants32 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
152 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
153 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
154 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
155 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
156 _variant31 };
|
jpayne@69
|
157 enum class Variants33 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
158 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
159 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
160 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
161 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
162 _variant31, _variant32 };
|
jpayne@69
|
163 enum class Variants34 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
164 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
165 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
166 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
167 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
168 _variant31, _variant32, _variant33 };
|
jpayne@69
|
169 enum class Variants35 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
170 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
171 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
172 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
173 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
174 _variant31, _variant32, _variant33, _variant34 };
|
jpayne@69
|
175 enum class Variants36 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
176 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
177 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
178 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
179 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
180 _variant31, _variant32, _variant33, _variant34, _variant35 };
|
jpayne@69
|
181 enum class Variants37 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
182 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
183 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
184 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
185 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
186 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36 };
|
jpayne@69
|
187 enum class Variants38 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
188 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
189 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
190 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
191 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
192 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
193 _variant37 };
|
jpayne@69
|
194 enum class Variants39 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
195 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
196 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
197 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
198 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
199 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
200 _variant37, _variant38 };
|
jpayne@69
|
201 enum class Variants40 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
202 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
203 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
204 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
205 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
206 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
207 _variant37, _variant38, _variant39 };
|
jpayne@69
|
208 enum class Variants41 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
209 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
210 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
211 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
212 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
213 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
214 _variant37, _variant38, _variant39, _variant40 };
|
jpayne@69
|
215 enum class Variants42 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
216 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
217 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
218 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
219 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
220 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
221 _variant37, _variant38, _variant39, _variant40, _variant41 };
|
jpayne@69
|
222 enum class Variants43 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
223 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
224 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
225 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
226 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
227 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
228 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42 };
|
jpayne@69
|
229 enum class Variants44 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
230 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
231 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
232 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
233 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
234 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
235 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
236 _variant43 };
|
jpayne@69
|
237 enum class Variants45 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
238 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
239 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
240 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
241 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
242 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
243 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
244 _variant43, _variant44 };
|
jpayne@69
|
245 enum class Variants46 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
246 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
247 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
248 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
249 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
250 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
251 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
252 _variant43, _variant44, _variant45 };
|
jpayne@69
|
253 enum class Variants47 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
254 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
255 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
256 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
257 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
258 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
259 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
260 _variant43, _variant44, _variant45, _variant46 };
|
jpayne@69
|
261 enum class Variants48 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
262 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
263 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
264 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
265 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
266 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
267 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
268 _variant43, _variant44, _variant45, _variant46, _variant47 };
|
jpayne@69
|
269 enum class Variants49 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
270 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
271 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
272 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
273 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
274 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
275 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
276 _variant43, _variant44, _variant45, _variant46, _variant47, _variant48 };
|
jpayne@69
|
277 enum class Variants50 { _variant0, _variant1, _variant2, _variant3, _variant4, _variant5, _variant6,
|
jpayne@69
|
278 _variant7, _variant8, _variant9, _variant10, _variant11, _variant12,
|
jpayne@69
|
279 _variant13, _variant14, _variant15, _variant16, _variant17, _variant18,
|
jpayne@69
|
280 _variant19, _variant20, _variant21, _variant22, _variant23, _variant24,
|
jpayne@69
|
281 _variant25, _variant26, _variant27, _variant28, _variant29, _variant30,
|
jpayne@69
|
282 _variant31, _variant32, _variant33, _variant34, _variant35, _variant36,
|
jpayne@69
|
283 _variant37, _variant38, _variant39, _variant40, _variant41, _variant42,
|
jpayne@69
|
284 _variant43, _variant44, _variant45, _variant46, _variant47, _variant48,
|
jpayne@69
|
285 _variant49 };
|
jpayne@69
|
286
|
jpayne@69
|
287 template <uint i> struct Variants_;
|
jpayne@69
|
288 template <> struct Variants_<0> { typedef Variants0 Type; };
|
jpayne@69
|
289 template <> struct Variants_<1> { typedef Variants1 Type; };
|
jpayne@69
|
290 template <> struct Variants_<2> { typedef Variants2 Type; };
|
jpayne@69
|
291 template <> struct Variants_<3> { typedef Variants3 Type; };
|
jpayne@69
|
292 template <> struct Variants_<4> { typedef Variants4 Type; };
|
jpayne@69
|
293 template <> struct Variants_<5> { typedef Variants5 Type; };
|
jpayne@69
|
294 template <> struct Variants_<6> { typedef Variants6 Type; };
|
jpayne@69
|
295 template <> struct Variants_<7> { typedef Variants7 Type; };
|
jpayne@69
|
296 template <> struct Variants_<8> { typedef Variants8 Type; };
|
jpayne@69
|
297 template <> struct Variants_<9> { typedef Variants9 Type; };
|
jpayne@69
|
298 template <> struct Variants_<10> { typedef Variants10 Type; };
|
jpayne@69
|
299 template <> struct Variants_<11> { typedef Variants11 Type; };
|
jpayne@69
|
300 template <> struct Variants_<12> { typedef Variants12 Type; };
|
jpayne@69
|
301 template <> struct Variants_<13> { typedef Variants13 Type; };
|
jpayne@69
|
302 template <> struct Variants_<14> { typedef Variants14 Type; };
|
jpayne@69
|
303 template <> struct Variants_<15> { typedef Variants15 Type; };
|
jpayne@69
|
304 template <> struct Variants_<16> { typedef Variants16 Type; };
|
jpayne@69
|
305 template <> struct Variants_<17> { typedef Variants17 Type; };
|
jpayne@69
|
306 template <> struct Variants_<18> { typedef Variants18 Type; };
|
jpayne@69
|
307 template <> struct Variants_<19> { typedef Variants19 Type; };
|
jpayne@69
|
308 template <> struct Variants_<20> { typedef Variants20 Type; };
|
jpayne@69
|
309 template <> struct Variants_<21> { typedef Variants21 Type; };
|
jpayne@69
|
310 template <> struct Variants_<22> { typedef Variants22 Type; };
|
jpayne@69
|
311 template <> struct Variants_<23> { typedef Variants23 Type; };
|
jpayne@69
|
312 template <> struct Variants_<24> { typedef Variants24 Type; };
|
jpayne@69
|
313 template <> struct Variants_<25> { typedef Variants25 Type; };
|
jpayne@69
|
314 template <> struct Variants_<26> { typedef Variants26 Type; };
|
jpayne@69
|
315 template <> struct Variants_<27> { typedef Variants27 Type; };
|
jpayne@69
|
316 template <> struct Variants_<28> { typedef Variants28 Type; };
|
jpayne@69
|
317 template <> struct Variants_<29> { typedef Variants29 Type; };
|
jpayne@69
|
318 template <> struct Variants_<30> { typedef Variants30 Type; };
|
jpayne@69
|
319 template <> struct Variants_<31> { typedef Variants31 Type; };
|
jpayne@69
|
320 template <> struct Variants_<32> { typedef Variants32 Type; };
|
jpayne@69
|
321 template <> struct Variants_<33> { typedef Variants33 Type; };
|
jpayne@69
|
322 template <> struct Variants_<34> { typedef Variants34 Type; };
|
jpayne@69
|
323 template <> struct Variants_<35> { typedef Variants35 Type; };
|
jpayne@69
|
324 template <> struct Variants_<36> { typedef Variants36 Type; };
|
jpayne@69
|
325 template <> struct Variants_<37> { typedef Variants37 Type; };
|
jpayne@69
|
326 template <> struct Variants_<38> { typedef Variants38 Type; };
|
jpayne@69
|
327 template <> struct Variants_<39> { typedef Variants39 Type; };
|
jpayne@69
|
328 template <> struct Variants_<40> { typedef Variants40 Type; };
|
jpayne@69
|
329 template <> struct Variants_<41> { typedef Variants41 Type; };
|
jpayne@69
|
330 template <> struct Variants_<42> { typedef Variants42 Type; };
|
jpayne@69
|
331 template <> struct Variants_<43> { typedef Variants43 Type; };
|
jpayne@69
|
332 template <> struct Variants_<44> { typedef Variants44 Type; };
|
jpayne@69
|
333 template <> struct Variants_<45> { typedef Variants45 Type; };
|
jpayne@69
|
334 template <> struct Variants_<46> { typedef Variants46 Type; };
|
jpayne@69
|
335 template <> struct Variants_<47> { typedef Variants47 Type; };
|
jpayne@69
|
336 template <> struct Variants_<48> { typedef Variants48 Type; };
|
jpayne@69
|
337 template <> struct Variants_<49> { typedef Variants49 Type; };
|
jpayne@69
|
338 template <> struct Variants_<50> { typedef Variants50 Type; };
|
jpayne@69
|
339
|
jpayne@69
|
340 template <uint i>
|
jpayne@69
|
341 using Variants = typename Variants_<i>::Type;
|
jpayne@69
|
342
|
jpayne@69
|
343 } // namespace _ (private)
|
jpayne@69
|
344
|
jpayne@69
|
345 template <typename... Variants>
|
jpayne@69
|
346 class OneOf {
|
jpayne@69
|
347 template <typename Key>
|
jpayne@69
|
348 static inline constexpr uint typeIndex() {
|
jpayne@69
|
349 return _::TypeIndex_<1, _::OneOfFailError_, Key, Variants...>::value;
|
jpayne@69
|
350 }
|
jpayne@69
|
351 // Get the 1-based index of Key within the type list Types, or static_assert with a nice error.
|
jpayne@69
|
352
|
jpayne@69
|
353 template <typename Key>
|
jpayne@69
|
354 static inline constexpr uint typeIndexOrZero() {
|
jpayne@69
|
355 return _::TypeIndex_<1, _::OneOfFailZero_, Key, Variants...>::value;
|
jpayne@69
|
356 }
|
jpayne@69
|
357
|
jpayne@69
|
358 template <uint i, typename... OtherVariants>
|
jpayne@69
|
359 struct HasAll;
|
jpayne@69
|
360 // Has a member type called "Success" if and only if all of `OtherVariants` are types that
|
jpayne@69
|
361 // appear in `Variants`. Used with SFINAE to enable subset constructors.
|
jpayne@69
|
362
|
jpayne@69
|
363 public:
|
jpayne@69
|
364 inline OneOf(): tag(0) {}
|
jpayne@69
|
365
|
jpayne@69
|
366 OneOf(const OneOf& other) { copyFrom(other); }
|
jpayne@69
|
367 OneOf(OneOf& other) { copyFrom(other); }
|
jpayne@69
|
368 OneOf(OneOf&& other) { moveFrom(other); }
|
jpayne@69
|
369 // Copy/move from same OneOf type.
|
jpayne@69
|
370
|
jpayne@69
|
371 template <typename... OtherVariants, typename = typename HasAll<1, OtherVariants...>::Success>
|
jpayne@69
|
372 OneOf(const OneOf<OtherVariants...>& other) { copyFromSubset(other); }
|
jpayne@69
|
373 template <typename... OtherVariants, typename = typename HasAll<1, OtherVariants...>::Success>
|
jpayne@69
|
374 OneOf(OneOf<OtherVariants...>& other) { copyFromSubset(other); }
|
jpayne@69
|
375 template <typename... OtherVariants, typename = typename HasAll<1, OtherVariants...>::Success>
|
jpayne@69
|
376 OneOf(OneOf<OtherVariants...>&& other) { moveFromSubset(other); }
|
jpayne@69
|
377 // Copy/move from OneOf that contains a subset of the types we do.
|
jpayne@69
|
378
|
jpayne@69
|
379 template <typename T, typename = typename HasAll<0, Decay<T>>::Success>
|
jpayne@69
|
380 OneOf(T&& other): tag(typeIndex<Decay<T>>()) {
|
jpayne@69
|
381 ctor(*reinterpret_cast<Decay<T>*>(space), kj::fwd<T>(other));
|
jpayne@69
|
382 }
|
jpayne@69
|
383 // Copy/move from a value that matches one of the individual types in the OneOf.
|
jpayne@69
|
384
|
jpayne@69
|
385 ~OneOf() { destroy(); }
|
jpayne@69
|
386
|
jpayne@69
|
387 OneOf& operator=(const OneOf& other) { if (tag != 0) destroy(); copyFrom(other); return *this; }
|
jpayne@69
|
388 OneOf& operator=(OneOf&& other) { if (tag != 0) destroy(); moveFrom(other); return *this; }
|
jpayne@69
|
389
|
jpayne@69
|
390 inline bool operator==(decltype(nullptr)) const { return tag == 0; }
|
jpayne@69
|
391 inline bool operator!=(decltype(nullptr)) const { return tag != 0; }
|
jpayne@69
|
392
|
jpayne@69
|
393 template <typename T>
|
jpayne@69
|
394 bool is() const {
|
jpayne@69
|
395 return tag == typeIndex<T>();
|
jpayne@69
|
396 }
|
jpayne@69
|
397
|
jpayne@69
|
398 template <typename T>
|
jpayne@69
|
399 T& get() & {
|
jpayne@69
|
400 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
|
jpayne@69
|
401 return *reinterpret_cast<T*>(space);
|
jpayne@69
|
402 }
|
jpayne@69
|
403 template <typename T>
|
jpayne@69
|
404 T&& get() && {
|
jpayne@69
|
405 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
|
jpayne@69
|
406 return kj::mv(*reinterpret_cast<T*>(space));
|
jpayne@69
|
407 }
|
jpayne@69
|
408 template <typename T>
|
jpayne@69
|
409 const T& get() const& {
|
jpayne@69
|
410 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
|
jpayne@69
|
411 return *reinterpret_cast<const T*>(space);
|
jpayne@69
|
412 }
|
jpayne@69
|
413 template <typename T>
|
jpayne@69
|
414 const T&& get() const&& {
|
jpayne@69
|
415 KJ_IREQUIRE(is<T>(), "Must check OneOf::is<T>() before calling get<T>().");
|
jpayne@69
|
416 return kj::mv(*reinterpret_cast<const T*>(space));
|
jpayne@69
|
417 }
|
jpayne@69
|
418
|
jpayne@69
|
419 template <typename T, typename... Params>
|
jpayne@69
|
420 T& init(Params&&... params) {
|
jpayne@69
|
421 if (tag != 0) destroy();
|
jpayne@69
|
422 ctor(*reinterpret_cast<T*>(space), kj::fwd<Params>(params)...);
|
jpayne@69
|
423 tag = typeIndex<T>();
|
jpayne@69
|
424 return *reinterpret_cast<T*>(space);
|
jpayne@69
|
425 }
|
jpayne@69
|
426
|
jpayne@69
|
427 template <typename T>
|
jpayne@69
|
428 Maybe<T&> tryGet() {
|
jpayne@69
|
429 if (is<T>()) {
|
jpayne@69
|
430 return *reinterpret_cast<T*>(space);
|
jpayne@69
|
431 } else {
|
jpayne@69
|
432 return nullptr;
|
jpayne@69
|
433 }
|
jpayne@69
|
434 }
|
jpayne@69
|
435 template <typename T>
|
jpayne@69
|
436 Maybe<const T&> tryGet() const {
|
jpayne@69
|
437 if (is<T>()) {
|
jpayne@69
|
438 return *reinterpret_cast<const T*>(space);
|
jpayne@69
|
439 } else {
|
jpayne@69
|
440 return nullptr;
|
jpayne@69
|
441 }
|
jpayne@69
|
442 }
|
jpayne@69
|
443
|
jpayne@69
|
444 template <uint i>
|
jpayne@69
|
445 KJ_NORETURN(void allHandled());
|
jpayne@69
|
446 // After a series of if/else blocks handling each variant of the OneOf, have the final else
|
jpayne@69
|
447 // block call allHandled<n>() where n is the number of variants. This will fail to compile
|
jpayne@69
|
448 // if new variants are added in the future.
|
jpayne@69
|
449
|
jpayne@69
|
450 typedef _::Variants<sizeof...(Variants)> Tag;
|
jpayne@69
|
451
|
jpayne@69
|
452 Tag which() const {
|
jpayne@69
|
453 KJ_IREQUIRE(tag != 0, "Can't KJ_SWITCH_ONEOF() on uninitialized value.");
|
jpayne@69
|
454 return static_cast<Tag>(tag - 1);
|
jpayne@69
|
455 }
|
jpayne@69
|
456
|
jpayne@69
|
457 template <typename T>
|
jpayne@69
|
458 static constexpr Tag tagFor() {
|
jpayne@69
|
459 return static_cast<Tag>(typeIndex<T>() - 1);
|
jpayne@69
|
460 }
|
jpayne@69
|
461
|
jpayne@69
|
462 OneOf* _switchSubject() & { return this; }
|
jpayne@69
|
463 const OneOf* _switchSubject() const& { return this; }
|
jpayne@69
|
464 _::NullableValue<OneOf> _switchSubject() && { return kj::mv(*this); }
|
jpayne@69
|
465
|
jpayne@69
|
466 private:
|
jpayne@69
|
467 uint tag;
|
jpayne@69
|
468
|
jpayne@69
|
469 static inline constexpr size_t maxSize(size_t a) {
|
jpayne@69
|
470 return a;
|
jpayne@69
|
471 }
|
jpayne@69
|
472 template <typename... Rest>
|
jpayne@69
|
473 static inline constexpr size_t maxSize(size_t a, size_t b, Rest... rest) {
|
jpayne@69
|
474 return maxSize(kj::max(a, b), rest...);
|
jpayne@69
|
475 }
|
jpayne@69
|
476 // Returns the maximum of all the parameters.
|
jpayne@69
|
477 // TODO(someday): Generalize the above template and make it common. I tried, but C++ decided to
|
jpayne@69
|
478 // be difficult so I cut my losses.
|
jpayne@69
|
479
|
jpayne@69
|
480 static constexpr auto spaceSize = maxSize(sizeof(Variants)...);
|
jpayne@69
|
481 // TODO(msvc): This constant could just as well go directly inside space's bracket's, where it's
|
jpayne@69
|
482 // used, but MSVC suffers a parse error on `...`.
|
jpayne@69
|
483
|
jpayne@69
|
484 union {
|
jpayne@69
|
485 byte space[spaceSize];
|
jpayne@69
|
486
|
jpayne@69
|
487 void* forceAligned;
|
jpayne@69
|
488 // TODO(someday): Use C++11 alignas() once we require GCC 4.8 / Clang 3.3.
|
jpayne@69
|
489 };
|
jpayne@69
|
490
|
jpayne@69
|
491 template <typename... T>
|
jpayne@69
|
492 inline void doAll(T... t) {}
|
jpayne@69
|
493
|
jpayne@69
|
494 template <typename T>
|
jpayne@69
|
495 inline bool destroyVariant() {
|
jpayne@69
|
496 if (tag == typeIndex<T>()) {
|
jpayne@69
|
497 tag = 0;
|
jpayne@69
|
498 dtor(*reinterpret_cast<T*>(space));
|
jpayne@69
|
499 }
|
jpayne@69
|
500 return false;
|
jpayne@69
|
501 }
|
jpayne@69
|
502 void destroy() {
|
jpayne@69
|
503 doAll(destroyVariant<Variants>()...);
|
jpayne@69
|
504 }
|
jpayne@69
|
505
|
jpayne@69
|
506 template <typename T>
|
jpayne@69
|
507 inline bool copyVariantFrom(const OneOf& other) {
|
jpayne@69
|
508 if (other.is<T>()) {
|
jpayne@69
|
509 ctor(*reinterpret_cast<T*>(space), other.get<T>());
|
jpayne@69
|
510 }
|
jpayne@69
|
511 return false;
|
jpayne@69
|
512 }
|
jpayne@69
|
513 void copyFrom(const OneOf& other) {
|
jpayne@69
|
514 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag
|
jpayne@69
|
515 // is invalid.
|
jpayne@69
|
516 tag = other.tag;
|
jpayne@69
|
517 doAll(copyVariantFrom<Variants>(other)...);
|
jpayne@69
|
518 }
|
jpayne@69
|
519
|
jpayne@69
|
520 template <typename T>
|
jpayne@69
|
521 inline bool copyVariantFrom(OneOf& other) {
|
jpayne@69
|
522 if (other.is<T>()) {
|
jpayne@69
|
523 ctor(*reinterpret_cast<T*>(space), other.get<T>());
|
jpayne@69
|
524 }
|
jpayne@69
|
525 return false;
|
jpayne@69
|
526 }
|
jpayne@69
|
527 void copyFrom(OneOf& other) {
|
jpayne@69
|
528 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag
|
jpayne@69
|
529 // is invalid.
|
jpayne@69
|
530 tag = other.tag;
|
jpayne@69
|
531 doAll(copyVariantFrom<Variants>(other)...);
|
jpayne@69
|
532 }
|
jpayne@69
|
533
|
jpayne@69
|
534 template <typename T>
|
jpayne@69
|
535 inline bool moveVariantFrom(OneOf& other) {
|
jpayne@69
|
536 if (other.is<T>()) {
|
jpayne@69
|
537 ctor(*reinterpret_cast<T*>(space), kj::mv(other.get<T>()));
|
jpayne@69
|
538 }
|
jpayne@69
|
539 return false;
|
jpayne@69
|
540 }
|
jpayne@69
|
541 void moveFrom(OneOf& other) {
|
jpayne@69
|
542 // Initialize as a copy of `other`. Expects that `this` starts out uninitialized, so the tag
|
jpayne@69
|
543 // is invalid.
|
jpayne@69
|
544 tag = other.tag;
|
jpayne@69
|
545 doAll(moveVariantFrom<Variants>(other)...);
|
jpayne@69
|
546 }
|
jpayne@69
|
547
|
jpayne@69
|
548 template <typename T, typename... OtherVariants>
|
jpayne@69
|
549 inline bool copySubsetVariantFrom(const OneOf<OtherVariants...>& other) {
|
jpayne@69
|
550 if (other.template is<T>()) {
|
jpayne@69
|
551 tag = typeIndex<Decay<T>>();
|
jpayne@69
|
552 ctor(*reinterpret_cast<T*>(space), other.template get<T>());
|
jpayne@69
|
553 }
|
jpayne@69
|
554 return false;
|
jpayne@69
|
555 }
|
jpayne@69
|
556 template <typename... OtherVariants>
|
jpayne@69
|
557 void copyFromSubset(const OneOf<OtherVariants...>& other) {
|
jpayne@69
|
558 doAll(copySubsetVariantFrom<OtherVariants>(other)...);
|
jpayne@69
|
559 }
|
jpayne@69
|
560
|
jpayne@69
|
561 template <typename T, typename... OtherVariants>
|
jpayne@69
|
562 inline bool copySubsetVariantFrom(OneOf<OtherVariants...>& other) {
|
jpayne@69
|
563 if (other.template is<T>()) {
|
jpayne@69
|
564 tag = typeIndex<Decay<T>>();
|
jpayne@69
|
565 ctor(*reinterpret_cast<T*>(space), other.template get<T>());
|
jpayne@69
|
566 }
|
jpayne@69
|
567 return false;
|
jpayne@69
|
568 }
|
jpayne@69
|
569 template <typename... OtherVariants>
|
jpayne@69
|
570 void copyFromSubset(OneOf<OtherVariants...>& other) {
|
jpayne@69
|
571 doAll(copySubsetVariantFrom<OtherVariants>(other)...);
|
jpayne@69
|
572 }
|
jpayne@69
|
573
|
jpayne@69
|
574 template <typename T, typename... OtherVariants>
|
jpayne@69
|
575 inline bool moveSubsetVariantFrom(OneOf<OtherVariants...>& other) {
|
jpayne@69
|
576 if (other.template is<T>()) {
|
jpayne@69
|
577 tag = typeIndex<Decay<T>>();
|
jpayne@69
|
578 ctor(*reinterpret_cast<T*>(space), kj::mv(other.template get<T>()));
|
jpayne@69
|
579 }
|
jpayne@69
|
580 return false;
|
jpayne@69
|
581 }
|
jpayne@69
|
582 template <typename... OtherVariants>
|
jpayne@69
|
583 void moveFromSubset(OneOf<OtherVariants...>& other) {
|
jpayne@69
|
584 doAll(moveSubsetVariantFrom<OtherVariants>(other)...);
|
jpayne@69
|
585 }
|
jpayne@69
|
586 };
|
jpayne@69
|
587
|
jpayne@69
|
588 template <typename... Variants>
|
jpayne@69
|
589 template <uint i, typename First, typename... Rest>
|
jpayne@69
|
590 struct OneOf<Variants...>::HasAll<i, First, Rest...>
|
jpayne@69
|
591 : public HasAll<typeIndexOrZero<First>(), Rest...> {};
|
jpayne@69
|
592 template <typename... Variants>
|
jpayne@69
|
593 template <uint i>
|
jpayne@69
|
594 struct OneOf<Variants...>::HasAll<i>: public _::SuccessIfNotZero<i> {};
|
jpayne@69
|
595
|
jpayne@69
|
596 template <typename... Variants>
|
jpayne@69
|
597 template <uint i>
|
jpayne@69
|
598 void OneOf<Variants...>::allHandled() {
|
jpayne@69
|
599 // After a series of if/else blocks handling each variant of the OneOf, have the final else
|
jpayne@69
|
600 // block call allHandled<n>() where n is the number of variants. This will fail to compile
|
jpayne@69
|
601 // if new variants are added in the future.
|
jpayne@69
|
602
|
jpayne@69
|
603 static_assert(i == sizeof...(Variants), "new OneOf variants need to be handled here");
|
jpayne@69
|
604 KJ_UNREACHABLE;
|
jpayne@69
|
605 }
|
jpayne@69
|
606
|
jpayne@69
|
607 #if KJ_CPP_STD > 201402L
|
jpayne@69
|
608 #define KJ_SWITCH_ONEOF(value) \
|
jpayne@69
|
609 switch (auto _kj_switch_subject = (value)._switchSubject(); _kj_switch_subject->which())
|
jpayne@69
|
610 #else
|
jpayne@69
|
611 #define KJ_SWITCH_ONEOF(value) \
|
jpayne@69
|
612 /* Without C++17, we can only support one switch per containing block. Deal with it. */ \
|
jpayne@69
|
613 auto _kj_switch_subject = (value)._switchSubject(); \
|
jpayne@69
|
614 switch (_kj_switch_subject->which())
|
jpayne@69
|
615 #endif
|
jpayne@69
|
616 #if !_MSC_VER || defined(__clang__)
|
jpayne@69
|
617 #define KJ_CASE_ONEOF(name, ...) \
|
jpayne@69
|
618 break; \
|
jpayne@69
|
619 case ::kj::Decay<decltype(*_kj_switch_subject)>::template tagFor<__VA_ARGS__>(): \
|
jpayne@69
|
620 for (auto& name = _kj_switch_subject->template get<__VA_ARGS__>(), *_kj_switch_done = &name; \
|
jpayne@69
|
621 _kj_switch_done; _kj_switch_done = nullptr)
|
jpayne@69
|
622 #else
|
jpayne@69
|
623 // TODO(msvc): The latest MSVC which ships with VS2019 now ICEs on the implementation above. It
|
jpayne@69
|
624 // appears we can hack around the problem by moving the `->template get<>()` syntax to an outer
|
jpayne@69
|
625 // `if`. (This unfortunately allows wonky syntax like `KJ_CASE_ONEOF(a, B) { } else { }`.)
|
jpayne@69
|
626 // https://developercommunity.visualstudio.com/content/problem/1143733/internal-compiler-error-on-v1670.html
|
jpayne@69
|
627 #define KJ_CASE_ONEOF(name, ...) \
|
jpayne@69
|
628 break; \
|
jpayne@69
|
629 case ::kj::Decay<decltype(*_kj_switch_subject)>::template tagFor<__VA_ARGS__>(): \
|
jpayne@69
|
630 if (auto* _kj_switch_done = &_kj_switch_subject->template get<__VA_ARGS__>()) \
|
jpayne@69
|
631 for (auto& name = *_kj_switch_done; _kj_switch_done; _kj_switch_done = nullptr)
|
jpayne@69
|
632 #endif
|
jpayne@69
|
633 #define KJ_CASE_ONEOF_DEFAULT break; default:
|
jpayne@69
|
634 // Allows switching over a OneOf.
|
jpayne@69
|
635 //
|
jpayne@69
|
636 // Example:
|
jpayne@69
|
637 //
|
jpayne@69
|
638 // kj::OneOf<int, float, const char*> variant;
|
jpayne@69
|
639 // KJ_SWITCH_ONEOF(variant) {
|
jpayne@69
|
640 // KJ_CASE_ONEOF(i, int) {
|
jpayne@69
|
641 // doSomethingWithInt(i);
|
jpayne@69
|
642 // }
|
jpayne@69
|
643 // KJ_CASE_ONEOF(s, const char*) {
|
jpayne@69
|
644 // doSomethingWithString(s);
|
jpayne@69
|
645 // }
|
jpayne@69
|
646 // KJ_CASE_ONEOF_DEFAULT {
|
jpayne@69
|
647 // doSomethingElse();
|
jpayne@69
|
648 // }
|
jpayne@69
|
649 // }
|
jpayne@69
|
650 //
|
jpayne@69
|
651 // Notes:
|
jpayne@69
|
652 // - If you don't handle all possible types and don't include a default branch, you'll get a
|
jpayne@69
|
653 // compiler warning, just like a regular switch() over an enum where one of the enum values is
|
jpayne@69
|
654 // missing.
|
jpayne@69
|
655 // - There's no need for a `break` statement in a KJ_CASE_ONEOF; it is implied.
|
jpayne@69
|
656 // - Under C++11 and C++14, only one KJ_SWITCH_ONEOF() can appear in a block. Wrap the switch in
|
jpayne@69
|
657 // a pair of braces if you need a second switch in the same block. If C++17 is enabled, this is
|
jpayne@69
|
658 // not an issue.
|
jpayne@69
|
659 //
|
jpayne@69
|
660 // Implementation notes:
|
jpayne@69
|
661 // - The use of __VA_ARGS__ is to account for template types that have commas separating type
|
jpayne@69
|
662 // parameters, since macros don't recognize <> as grouping.
|
jpayne@69
|
663 // - _kj_switch_done is really used as a boolean flag to prevent the for() loop from actually
|
jpayne@69
|
664 // looping, but it's defined as a pointer since that's all we can define in this context.
|
jpayne@69
|
665
|
jpayne@69
|
666 } // namespace kj
|
jpayne@69
|
667
|
jpayne@69
|
668 KJ_END_HEADER
|