<div class="gmail_quote">On Thu, Aug 5, 2010 at 04:26, bearophile <span dir="ltr"><<a href="mailto:bearophileHUGS@lycos.com">bearophileHUGS@lycos.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
I have found one bad looking solution :-)<br>
<br>
template IsFoo(alias S) {<br>
enum bool IsFoo = __traits(compiles, { void isf(T...)(Foo!T){} isf(S.init); });<br>
}<br></blockquote><div><br></div><div>I used to be confronted to this pb too. Here is what I did:</div><div><br></div><div>/**</div><div>Alias itself to true if $(M T) is an instance of $(M templ). To obtain the template parameters,</div>
<div>see TemplateParametersTypeTuple.</div><div>Example:</div><div>----</div><div>auto cy = cycle([0,1,2,3]); // cy is a Cycle!(int[])</div><div>alias typeof(cy) Cy;</div><div>assert(isInstanceOf!(Cy, Cycle));</div><div>----</div>
<div>*/</div><div>template isInstanceOf(T, alias templ)</div><div>{</div><div> static if (T.stringof.length >= __traits(identifier, templ).length</div><div> && T.stringof[0..__traits(identifier, templ).length] == __traits(identifier, templ))</div>
<div> enum bool isInstanceOf = true;</div><div> else</div><div> enum bool isInstanceOf = false;</div><div>}</div><div><br></div><div><div>/**</div><div>Alias itself to true iff templ is a template name (standard, function, class or struct template).</div>
<div>*/</div><div>template isTemplate(alias templ)</div><div>{</div><div> static if (is(typeof(templ) == void) && is(typeof(templ.stringof)))</div><div> enum bool isTemplate = true;</div><div> else</div>
<div> enum bool isTemplate = false;</div><div>}</div></div><div><br></div><div><br></div><div>The converse is a bit more complicated: given a type T, of which you know it's a template instantiation (T == U!someTypes), get the (someTypes) as a typetuple.</div>
<div><br></div><div><br></div><div>string[3] between(char b, char e, string s)()</div><div>{</div><div> int foundb;</div><div> int ib;</div><div> string notFound = "";</div><div> foreach(i,c; s)</div>
<div> {</div><div> if (c==b)</div><div> {</div><div> if (foundb == 0)</div><div> {</div><div> foundb = 1;</div><div> ib = i+1;</div><div> continue;</div>
<div> }</div><div> else</div><div> {</div><div> ++foundb;</div><div> }</div><div> }</div><div> if (c==e)</div><div> {</div><div> if (foundb == 1)</div>
<div> {</div><div> return [s[0..ib-1], s[ib..i], s[i+1..$]]; // before b, between b and e, after e. Standard case.</div><div> }</div><div> else</div><div> {</div>
<div> --foundb;</div><div> }</div><div> }</div><div> }</div><div> return [s, notFound,notFound]; // no b found, explored the whole string</div><div>}</div><div><br></div><div> /**</div>
<div>Takes a type instantiating a template (that is, T == A!(someTypes...) for some A)</div><div>and becomes the template's parameters typetuple: TypeTuple!(someTypes) in the previous example.</div><div>It won't work for alias parameters, because they're not imported.</div>
<div>Example:</div><div>----</div><div>assert(is(TemplateParametersTypeTuple!(Cycle!(int[])) == TypeTuple!(int[])));</div><div>----</div><div>*/</div><div>template TemplateParametersTypeTuple(T)</div><div>{</div><div> mixin("alias TypeTuple!(" ~ between!('(',')',T.stringof)[1] ~ ") TemplateParametersTypeTuple;");</div>
<div>}</div><div><br></div><div>As a nice side-effect, you can also extract the template name:</div><div><br></div><div><div><div>/**</div><div>If T is a template instantiation, becomes the template name. For a non-templated type,</div>
<div>it just becomes this type name. </div><div>----</div><div>struct Foo(T...) {}</div><div>alias Foo!(int, double) Foo_id;</div><div>assert(TemplateName!(Foo_id) == "Foo");</div><div><br></div><div>assert(TemplateName!(int) == "int");</div>
<div>----</div><div>*/</div><div>template TemplateName(T)</div><div>{</div><div> enum string TemplateName = between!('!','(',T.stringof)[0];</div><div>}</div></div></div><div><br></div><div><br></div><div>
So, given T, you can</div><div>- determine if it's a template instantiation or not (TBD)</div><div>- extract the template name (and so, test for their equality)</div><div>- extract the template parameters, as a TypeTuple</div>
<div><br></div><div>I used this to transfer template parameters from one template to another:</div><div><br></div><div>FromXToBar(someFoo)</div><div> -> test if it's a template</div><div>-> extract the parameters</div>
<div>-> instantiate a Bar!Parameters.</div><div><br></div><div>So, given a Bar!(int,double), it creates a Foo!(int,double). It's a kind of function, from Bar to Foo...</div><div><br></div><div><br></div><div>It worked for me, tell me if it's OK for you.</div>
<div><br></div><div>Philippe</div><div><br></div></div>