1 /** 2 * Copyright: © 2014-2015 Anton Gushcha 3 * License: Subject to the terms of the Boost 1.0 license as specified in LICENSE file 4 * Authors: Anton Gushcha <ncrashed@gmail.com> 5 * 6 * Template for detecting overloads - extension of std.traits; 7 */ 8 module stribog.meta.overload; 9 10 import std.traits : isCallable, staticIndexOf, ReturnType, hasMember, ParameterTypeTuple; 11 12 import stribog.meta.base; 13 import stribog.meta.satisfy; 14 import stribog.meta.map; 15 16 /** 17 * Variant of std.traits.hasMember that checks also by member type 18 * to handle overloads. 19 * 20 * $(B T) is a type to be checked. $(B ElemType) is a member type, and 21 * $(B ElemName) is a member name. Template returns $(B true) if $(B T) has 22 * element (field or method) of type $(B ElemType) with name $(B ElemName). 23 * 24 * Template returns $(B false) for non aggregates. 25 */ 26 template hasOverload(T, ElemType, string ElemName) 27 { 28 static if(is(T == class) || is(T == struct) || is(T == interface) || is(T == union)) 29 { 30 static if(isCallable!ElemType) 31 { 32 alias retType = ReturnType!ElemType; 33 alias paramExpressionList = ParameterTypeTuple!ElemType; 34 35 private template extractType(alias F) 36 { 37 alias extractType = typeof(F); 38 } 39 40 static if(hasMember!(T, ElemName)) 41 alias overloads = staticMap!(extractType, __traits(getOverloads, T, ElemName)); 42 else 43 alias overloads = ExpressionList!(); 44 45 /// TODO: at next realease check overloads by attributes 46 //pragma(msg, __traits(getFunctionAttributes, sum)); 47 48 private template checkType(F) 49 { 50 static if(is(ReturnType!F == retType)) 51 { 52 enum checkType = staticEqual!(StrictExpressionList!(ParameterTypeTuple!F), StrictExpressionList!(paramExpressionList)); 53 } else 54 { 55 enum checkType = false; 56 } 57 } 58 59 enum hasOverload = anySatisfy!(checkType, overloads); 60 } 61 else 62 { 63 enum hasOverload = staticIndexOf!(ElemName, __traits(allMembers, T)) != -1 && 64 is(typeof(__traits(getMember, T, ElemName)) == ElemType); 65 } 66 } 67 else 68 { 69 enum hasOverload = false; 70 } 71 } 72 /// Example 73 unittest 74 { 75 struct A 76 { 77 bool method1(string a); 78 bool method1(float b); 79 string method1(); 80 81 string field; 82 } 83 84 static assert(hasOverload!(A, bool function(string), "method1")); 85 static assert(hasOverload!(A, bool function(float), "method1")); 86 static assert(hasOverload!(A, string function(), "method1")); 87 static assert(hasOverload!(A, string, "field")); 88 89 static assert(!hasOverload!(A, bool, "field")); 90 static assert(!hasOverload!(A, void function(), "method1")); 91 static assert(!hasOverload!(A, bool function(), "method1")); 92 static assert(!hasOverload!(A, string function(float), "method1")); 93 94 /// TODO: at next realease check overloads by attributes 95 // struct D 96 // { 97 // string toString() const {return "";} 98 // } 99 // 100 // static assert(hasOverload!(D, const string function(), "toString")); 101 // static assert(!hasOverload!(D, string function(), "toString")); 102 }