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