1 /** Trait for getting maximum size of types `T`.
2  *
3  * Implementation in `std.variant` uses recursion.
4  *
5  * See_Also: https://forum.dlang.org/post/hzpuiyxrrfasfuktpgqn@forum.dlang.org
6  */
7 module nxt.maxsize_trait;
8 
9 /** Get maximum size of types `Ts`.
10  *
11  * Limitation compared to `std.variant.maxSize`: `Ts` cannot contain `void`.
12  */
13 static template maxSizeOf(Ts...)
14 {
15     align(1) union Impl { Ts t; }
16  	enum maxSizeOf = Impl.sizeof;
17 }
18 
19 ///
20 @safe pure unittest
21 {
22     static assert(maxSizeOf!(char) == 1);
23     static assert(maxSizeOf!(byte) == 1);
24     static assert(maxSizeOf!(byte, short) == 2);
25     static assert(maxSizeOf!(short, byte) == 2);
26     static assert(maxSizeOf!(byte, short, int) == 4);
27     static assert(maxSizeOf!(byte, short, int, long) == 8);
28     static assert(maxSizeOf!(byte, short, int, string) == 16);
29     static assert(!__traits(compiles, { enum _ = maxSizeOf!(byte, void); }));
30 }
31 
32 // alternative implementation that supports `void`
33 static template maxSizeOf_1(Ts...)
34 {
35 	align(1) union Impl {
36 		static foreach (i, T; Ts) {
37 			static if (!is(T == void))
38                 mixin("T _field_" ~ i.stringof ~ ";");
39 		}
40 	}
41 	enum maxSizeOf_1 = Impl.sizeof;
42 }
43 
44 ///
45 @safe pure unittest
46 {
47     static assert(maxSizeOf_1!(char) == 1);
48     static assert(maxSizeOf_1!(byte) == 1);
49     static assert(maxSizeOf_1!(byte, short) == 2);
50     static assert(maxSizeOf_1!(short, byte) == 2);
51     static assert(maxSizeOf_1!(byte, short, int) == 4);
52     static assert(maxSizeOf_1!(byte, short, int, long) == 8);
53     static assert(maxSizeOf_1!(byte, short, int, string) == 16);
54     static assert(maxSizeOf_1!(byte, void) == 1);
55     static assert(maxSizeOf_1!(byte, short, void) == 2);
56 }