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 // version = nxt_benchmark; 10 11 /** Get maximum size of types `Ts`. 12 * 13 * Limitation compared to `std.variant.maxSize`: `Ts` cannot contain `void`. 14 */ 15 static template maxSizeOf(Ts...) 16 { 17 align(1) union Impl { Ts t; } 18 enum maxSizeOf = Impl.sizeof; 19 } 20 21 /// 22 pure @safe unittest { 23 static assert(maxSizeOf!(char) == 1); 24 static assert(maxSizeOf!(byte) == 1); 25 static assert(maxSizeOf!(byte, short) == 2); 26 static assert(maxSizeOf!(short, byte) == 2); 27 static assert(maxSizeOf!(byte, short, int) == 4); 28 static assert(maxSizeOf!(byte, short, int, long) == 8); 29 static assert(maxSizeOf!(byte, short, int, string) == 16); 30 static assert(!__traits(compiles, { enum _ = maxSizeOf!(byte, void); })); 31 } 32 33 // alternative implementation that supports `void` 34 static template maxSizeOf_1(Ts...) 35 { 36 align(1) union Impl { 37 static foreach (i, T; Ts) { 38 static if (!is(T == void)) 39 mixin("T _field_" ~ i.stringof ~ ";"); 40 } 41 } 42 enum maxSizeOf_1 = Impl.sizeof; 43 } 44 45 /// 46 pure @safe unittest { 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 } 57 58 template maxSizeOf_2(Ts...) 59 { 60 enum maxSizeOf_2 = compute(); 61 auto compute() 62 { 63 size_t result; 64 static foreach (T; Ts) 65 if (T.sizeof > result) 66 result = T.sizeof; 67 return result; 68 } 69 } 70 71 /// 72 pure @safe unittest { 73 static assert(maxSizeOf_2!(char) == 1); 74 static assert(maxSizeOf_2!(byte) == 1); 75 static assert(maxSizeOf_2!(byte, short) == 2); 76 static assert(maxSizeOf_2!(short, byte) == 2); 77 static assert(maxSizeOf_2!(byte, short, int) == 4); 78 static assert(maxSizeOf_2!(byte, short, int, long) == 8); 79 static assert(maxSizeOf_2!(byte, short, int, string) == 16); 80 static assert(maxSizeOf_2!(byte, void) == 1); 81 static assert(maxSizeOf_2!(byte, short, void) == 2); 82 } 83 84 struct W(T, size_t n) 85 { 86 T value; 87 } 88 89 version (nxt_benchmark) 90 void benchmark() 91 { 92 import std.meta : AliasSeq; 93 import std.traits : isCopyable; 94 alias Ts(uint n) = AliasSeq!(W!(byte, n), W!(ubyte, n), 95 W!(short, n), W!(ushort, n), 96 W!(int, n), W!(uint, n), 97 W!(long, n), W!(ulong, n), 98 W!(float, n), W!(cfloat, n), 99 W!(double, n), W!(cdouble, n), 100 W!(real, n), W!(creal, n), 101 W!(string, n), W!(wstring, n), W!(dstring, n)); 102 103 enum n = 100; 104 enum m = 100; 105 static foreach (i; 0 .. n) 106 { 107 foreach (T; Ts!(n)) 108 { 109 static foreach (j; 0 .. m) 110 { 111 static assert(maxSizeOf!(T) != 0); 112 } 113 } 114 } 115 }