1 /******************************************************************************* 2 3 Copyright: 4 Copyright (C) 2017 dunnhumby Germany GmbH. All rights reserved. 5 6 License: 7 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 8 Alternatively, this file may be distributed under the terms of the Tango 9 3-Clause BSD License (see LICENSE_BSD.txt for details). 10 11 *******************************************************************************/ 12 13 module ocean.meta.types.Templates; 14 15 /******************************************************************************* 16 17 Emulates `static if (Type : Template!(Args), Args...)`, which is a D2 18 feature 19 20 Given a template and an instance of it, allows to get the arguments used 21 to instantiate this type. 22 23 An example use case is when you want to wrap an aggregate which is templated 24 and need your `Wrapper` class to be templated on the aggregate's template 25 arguments: 26 --- 27 class Wrapper (TArgs...) { /+ Magic stuff +/ } 28 class Aggregate (TArgs...) { /+ Some more magic +/ } 29 30 Wrapper!(TemplateInstanceArgs!(Aggregate, Inst)) wrap (Inst) (Inst i) 31 { 32 auto wrapper = new Wrapper!(TemplateInstanceArgs!(Aggregate, Inst))(i); 33 return wrapper; 34 } 35 --- 36 37 This can also be used to see if a given symbol is an instance of a template: 38 `static if (is(TemplateInstanceArgs!(Template, PossibleInstance)))` 39 40 Note that eponymous templates can lead to surprising behaviour: 41 --- 42 template Identity (T) 43 { 44 alias T Identity; 45 } 46 47 // The following will fail, because `Identity!(char)` resolves to `char` ! 48 static assert(is(TemplateInstanceArgs!(Identity, Identity!(char)))); 49 --- 50 51 As a result, this template is better suited for template aggregates, 52 or templates with multiple members. 53 54 Params: 55 Template = The template symbol (uninstantiated) 56 Type = An instance of `Template` 57 58 *******************************************************************************/ 59 60 public template TemplateInstanceArgs (alias Template, Type : Template!(TA), TA...) 61 { 62 public alias TA TemplateInstanceArgs; 63 } 64 65 version (unittest) 66 { 67 private class BaseTestClass (T) {} 68 private class DerivedTestClass (T) : BaseTestClass!(T) {} 69 } 70 71 unittest 72 { 73 // Same type 74 static assert (is(TemplateInstanceArgs!(BaseTestClass, BaseTestClass!(int[])))); 75 // Derives 76 static assert (is(TemplateInstanceArgs!(BaseTestClass, DerivedTestClass!(int)))); 77 // Not a template 78 static assert (!is(TemplateInstanceArgs!(Object, BaseTestClass!(int)))); 79 // Not a type 80 static assert (!is(TemplateInstanceArgs!(BaseTestClass, BaseTestClass))); 81 // Doesn't derive / convert 82 static assert (!is(TemplateInstanceArgs!(int, BaseTestClass))); 83 } 84