1 /** 2 Additions to std.typetuple pending for inclusion into Phobos. 3 4 Copyright: © 2013 RejectedSoftware e.K. 5 License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 Authors: Михаил Страшун 7 */ 8 9 module vson.meta.typetuple; 10 11 import std.typetuple; 12 import std.traits; 13 14 /** 15 TypeTuple which does not auto-expand. 16 17 Useful when you need 18 to multiple several type tuples as different template argument 19 list parameters, without merging those. 20 */ 21 template Group(T...) 22 { 23 alias expand = T; 24 } 25 26 /// 27 unittest 28 { 29 alias group = Group!(int, double, string); 30 static assert (!is(typeof(group.length))); 31 static assert (group.expand.length == 3); 32 static assert (is(group.expand[1] == double)); 33 } 34 35 /** 36 */ 37 template isGroup(T...) 38 { 39 static if (T.length != 1) enum isGroup = false; 40 else enum isGroup = 41 !is(T[0]) && is(typeof(T[0]) == void) // does not evaluate to something 42 && is(typeof(T[0].expand.length) : size_t) // expands to something with length 43 && !is(typeof(&(T[0].expand))); // expands to not addressable 44 } 45 46 version (unittest) // NOTE: GDC complains about template definitions in unittest blocks 47 { 48 alias group = Group!(int, double, string); 49 alias group2 = Group!(); 50 51 template Fake(T...) 52 { 53 int[] expand; 54 } 55 alias fake = Fake!(int, double, string); 56 57 alias fake2 = TypeTuple!(int, double, string); 58 59 static assert (isGroup!group); 60 static assert (isGroup!group2); 61 static assert (!isGroup!fake); 62 static assert (!isGroup!fake2); 63 } 64 65 /* Copied from Phobos as it is private there. 66 */ 67 private template isSame(ab...) 68 if (ab.length == 2) 69 { 70 static if (is(ab[0]) && is(ab[1])) 71 { 72 enum isSame = is(ab[0] == ab[1]); 73 } 74 else static if (!is(ab[0]) && 75 !is(ab[1]) && 76 is(typeof(ab[0] == ab[1]) == bool) && 77 (ab[0] == ab[1])) 78 { 79 static if (!__traits(compiles, &ab[0]) || 80 !__traits(compiles, &ab[1])) 81 enum isSame = (ab[0] == ab[1]); 82 else 83 enum isSame = __traits(isSame, ab[0], ab[1]); 84 } 85 else 86 { 87 enum isSame = __traits(isSame, ab[0], ab[1]); 88 } 89 } 90 91 /** 92 Compares two groups for element identity 93 94 Params: 95 Group1, Group2 = any instances of `Group` 96 97 Returns: 98 `true` if each element of Group1 is identical to 99 the one of Group2 at the same index 100 */ 101 template Compare(alias Group1, alias Group2) 102 if (isGroup!Group1 && isGroup!Group2) 103 { 104 private bool implementation() 105 { 106 static if (Group1.expand.length == Group2.expand.length) { 107 foreach (index, element; Group1.expand) 108 { 109 static if (!isSame!(Group1.expand[index], Group2.expand[index])) { 110 return false; 111 } 112 } 113 return true; 114 } 115 else { 116 return false; 117 } 118 } 119 120 enum Compare = implementation(); 121 } 122 123 /// 124 unittest 125 { 126 alias one = Group!(int, double); 127 alias two = Group!(int, double); 128 alias three = Group!(double, int); 129 static assert (Compare!(one, two)); 130 static assert (!Compare!(one, three)); 131 }