1 /** 2 * Contains definition of hasTemplateMixin, which checks if a class or struct 3 * defines all the members of a template mixin, and hasStringMixin, which 4 * checks if a class or struct defines all the members of a string mixin. 5 */ 6 module quack.mixins; 7 import quack.extends; 8 9 import tested; 10 11 /** 12 * Checks if Child extends Parent by implementing a template mixin. 13 * 14 * Params: 15 * Child = The base class to test. 16 * mix = The mixin to test for. 17 * 18 * Returns: 19 * Whether Child has all the members of mix. 20 */ 21 template hasTemplateMixin( Child, alias mix ) 22 { 23 static if( isExtendable!Child ) 24 { 25 struct MixinImpl 26 { 27 mixin mix!(); 28 } 29 30 enum hasTemplateMixin = hasSameMembers!( Child, MixinImpl ); 31 } 32 else 33 { 34 enum hasTemplateMixin = false; 35 } 36 } 37 /// 38 @name( "hasTemplateMixin" ) 39 unittest 40 { 41 assert( !hasTemplateMixin!( float, TestMix ) ); 42 43 struct TestMixStruct1 44 { 45 mixin TestMix!(); 46 } 47 assert( hasTemplateMixin!( TestMixStruct1, TestMix ) ); 48 49 class TestMixClass1 50 { 51 mixin TestMix!(); 52 } 53 assert( hasTemplateMixin!( TestMixClass1, TestMix ) ); 54 55 class TestMixClass2 56 { 57 mixin TestMix!(); 58 int getY() { return 43; } 59 } 60 assert( hasTemplateMixin!( TestMixClass2, TestMix ) ); 61 62 class TestMixClass3 63 { 64 int getZ() { return 44; } 65 } 66 assert( !hasTemplateMixin!( TestMixClass3, TestMix ) ); 67 68 class TestMixClass4 69 { 70 int getX() { return 45; } 71 } 72 assert( hasTemplateMixin!( TestMixClass4, TestMix ) ); 73 } 74 version( unittest ) 75 mixin template TestMix() 76 { 77 int getX() { return 42; } 78 } 79 80 /** 81 * Checks if Child extends Parent by implementing a string mixin. 82 * 83 * Params: 84 * Child = The base class to test. 85 * mix = The mixin to test for. 86 * 87 * Returns: 88 * Whether Child has all the members of mix. 89 */ 90 template hasStringMixin( Base, string mix ) 91 { 92 static if( isExtendable!Base ) 93 { 94 struct MixinImpl 95 { 96 mixin( mix ); 97 } 98 99 enum hasStringMixin = hasSameMembers!( Base, MixinImpl ); 100 } 101 else 102 { 103 enum hasStringMixin = false; 104 } 105 } 106 /// 107 @name( "hasStringMixin" ) 108 unittest 109 { 110 enum testMix = q{ int getX() { return 42; } }; 111 112 assert( !hasStringMixin!( float, testMix ) ); 113 114 struct TestMixStruct1 115 { 116 mixin( testMix ); 117 } 118 assert( hasStringMixin!( TestMixStruct1, testMix ) ); 119 120 class TestMixClass1 121 { 122 mixin( testMix ); 123 } 124 assert( hasStringMixin!( TestMixClass1, testMix ) ); 125 126 class TestMixClass2 127 { 128 mixin( testMix ); 129 int getY() { return 43; } 130 } 131 assert( hasStringMixin!( TestMixClass2, testMix ) ); 132 133 class TestMixClass3 134 { 135 int getZ() { return 44; } 136 } 137 assert( !hasStringMixin!( TestMixClass3, testMix ) ); 138 139 class TestMixClass4 140 { 141 int getX() { return 45; } 142 } 143 assert( hasStringMixin!( TestMixClass4, testMix ) ); 144 }