1 module nxt.concatenation; 2 3 /** Sum of the lengths of the static arrays 'A'. 4 */ 5 template sumOfLengths(A...) 6 if (A.length) 7 { 8 static if (A.length == 1) 9 { 10 static if (isType!(A[0])) 11 { 12 static if (__traits(isStaticArray, A[0])) 13 { 14 enum sumOfLengths = A[0].length; 15 } 16 else 17 { 18 enum sumOfLengths = 1; 19 } 20 } 21 else 22 { 23 static if (__traits(isStaticArray, typeof(A[0]))) 24 { 25 enum sumOfLengths = A[0].length; 26 } 27 else 28 { 29 enum sumOfLengths = 1; 30 } 31 } 32 } 33 else 34 { 35 enum sumOfLengths = A[0].length + sumOfLengths!(A[1 .. $]); 36 } 37 } 38 39 /** Is `true` iff `T` is a type. */ 40 private template isType(T) { enum isType = true; } 41 /// ditto 42 private template isType(alias T) { enum isType = false; } 43 44 @safe pure nothrow @nogc unittest 45 { 46 int[2] x, y, z; 47 int w; 48 static assert(sumOfLengths!(x, y, z, w) == 7); 49 } 50 51 pragma(inline, true): // must be inlineable 52 53 /** Returns: concatenation of the static arrays `Args` as a static array. 54 * Move to Phobos's std.array. 55 */ 56 StaticArrayElementType!(Args[0])[sumOfLengths!Args] concatenate(Args...)(const auto ref Args args) 57 { 58 typeof(return) result = void; // @trusted 59 foreach (const i, arg; args) 60 { 61 static if (i == 0) 62 { 63 enum offset = 0; 64 } 65 else 66 { 67 enum offset = sumOfLengths!(args[0 .. i]); 68 } 69 static if (__traits(isStaticArray, typeof(arg))) 70 { 71 result[offset .. offset + arg.length] = arg[]; 72 } 73 else 74 { 75 result[offset] = arg; 76 } 77 } 78 return result; 79 } 80 81 private alias StaticArrayElementType(A : E[n], E, size_t n) = E; 82 83 @safe pure nothrow @nogc unittest 84 { 85 int[2] x = [11, 22]; 86 const int[2] y = [33, 44]; 87 const int w = 55; 88 auto z = concatenate(x, y, w); 89 static assert(is(typeof(z) == int[5])); 90 assert(z == [11, 22, 33, 44, 55]); 91 } 92 93 import core.internal.traits : hasElaborateDestructor; 94 import core.internal.traits : Unqual; 95 96 /** Overload with faster compilation. 97 */ 98 Unqual!T[n + 1] concatenate(T, size_t n)(auto ref T[n] a, T b) 99 if (!hasElaborateDestructor!T) 100 { 101 typeof(return) c = void; 102 c[0 .. n] = a; 103 c[n] = b; 104 return c; 105 } 106 107 @safe pure nothrow @nogc unittest 108 { 109 const int[2] x = [11, 22]; 110 int y = 33; 111 auto z = concatenate(x, y); 112 static assert(is(typeof(z) == int[3])); 113 assert(z == [11, 22, 33]); 114 }