1 /******************************************************************************* 2 3 Static reflection templates specific to various function-like types 4 5 NB: because this module is often used as purely compile-time dependency it 6 used built-in asserts instead of `ocean.core.Test` to reduce amount of 7 cyclic imports. `ocean.meta` modules in general are not supposed to 8 import anything outside of `ocean.meta`. 9 10 Copyright: 11 Copyright (c) 2017 dunnhumby Germany GmbH. All rights reserved. 12 13 License: 14 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 15 Alternatively, this file may be distributed under the terms of the Tango 16 3-Clause BSD License (see LICENSE_BSD.txt for details). 17 18 *******************************************************************************/ 19 20 module ocean.meta.types.Function; 21 22 import ocean.meta.AliasSeq; 23 import ocean.meta.traits.Basic; 24 import ocean.meta.types.Typedef; 25 26 /******************************************************************************* 27 28 Evaluates to a compile-time sequence representing the parameters of 29 Callable 30 31 Params: 32 Callable = callable type (function/delegate/function pointer) or 33 function symbol. Represented by variadic template of length 1 to 34 accept both types and function symbols. 35 36 *******************************************************************************/ 37 38 public template ParametersOf ( Callable... ) 39 { 40 static assert (Callable.length == 1); 41 42 static if (is(Callable[0] Params == function)) 43 alias AliasSeq!(Params) ParametersOf; 44 else static if (is(typeof(Callable[0]) Params == function)) 45 alias AliasSeq!(Params) ParametersOf; 46 else static if (is(Callable[0] TDgPtr == delegate)) 47 alias AliasSeq!(ParametersOf!(TDgPtr)) ParametersOf; 48 else static if (is(Callable[0] TFunc == TFunc*)) 49 alias AliasSeq!(ParametersOf!(TFunc)) ParametersOf; 50 else static if (isTypedef!(Callable[0])) 51 alias ParametersOf!(TypedefBaseType!(Callable[0])) ParametersOf; 52 else 53 static assert (false, "Argument is not a function"); 54 } 55 56 /// 57 unittest 58 { 59 void foo(int x, ref double y, char[] z) {} 60 alias ParametersOf!(typeof(foo)) Params; 61 62 static assert (Params.length == 3); 63 static assert (is(Params[0] == int)); 64 static assert (is(Params[1] == double)); 65 static assert (is(Params[2] == char[])); 66 } 67 68 unittest 69 { 70 void foo(int x, ref double y, char[] z) {} 71 alias ParametersOf!(typeof(&foo)) Params; 72 73 static assert (Params.length == 3); 74 static assert (is(Params[0] == int)); 75 static assert (is(Params[1] == double)); 76 static assert (is(Params[2] == char[])); 77 } 78 79 unittest 80 { 81 void delegate(int x, ref double y, char[] z) dg; 82 alias ParametersOf!(typeof(dg)) Params; 83 84 static assert (Params.length == 3); 85 static assert (is(Params[0] == int)); 86 static assert (is(Params[1] == double)); 87 static assert (is(Params[2] == char[])); 88 } 89 90 /******************************************************************************* 91 92 Deduces return type of a callable 93 94 Params: 95 Callable = callable type (function/delegate/function pointer) or 96 function symbol. Represented by variadic template of length 1 to 97 accept both types and function symbols. 98 99 Returns: 100 evaluates to return type of the callable 101 102 *******************************************************************************/ 103 104 public template ReturnTypeOf ( Callable... ) 105 { 106 static assert (Callable.length == 1); 107 108 static if (is(typeof(Callable[0]) == function)) 109 { 110 alias typeof({ 111 ParametersOf!(Callable[0]) args; 112 return Callable[0](args); 113 } ()) ReturnTypeOf; 114 } 115 else 116 { 117 alias typeof({ 118 ParametersOf!(Callable[0]) args; 119 Callable[0] call; 120 return call(args); 121 } ()) ReturnTypeOf; 122 } 123 } 124 125 /// 126 unittest 127 { 128 static assert (is(ReturnTypeOf!(void function()) == void)); 129 static assert (is(ReturnTypeOf!(int function(char)) == int)); 130 static assert (is(ReturnTypeOf!(int delegate(char)) == int)); 131 132 double foo ( char[], int ) { return 0; } 133 static assert (is(ReturnTypeOf!(foo) == double)); 134 static assert (is(ReturnTypeOf!(typeof(&foo)) == double)); 135 136 static assert (is(ReturnTypeOf!(int delegate(ref int)) == int)); 137 } 138 139 unittest 140 { 141 mixin (Typedef!(int, "MyType")); 142 MyType foo2() { return MyType.init; } 143 static assert (is(ReturnTypeOf!(foo2) == MyType)); 144 145 mixin (Typedef!(double function(), "MyFuncType")); 146 alias ReturnTypeOf!(MyFuncType) X; 147 static assert (is(ReturnTypeOf!(MyFuncType) == double)); 148 }