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