<div class="gmail_quote">On Thu, Aug 5, 2010 at 04:26, bearophile <span dir="ltr">&lt;<a href="mailto:bearophileHUGS@lycos.com">bearophileHUGS@lycos.com</a>&gt;</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 &gt;= __traits(identifier, templ).length</div><div>            &amp;&amp; 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) &amp;&amp; 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&#39;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 = &quot;&quot;;</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&#39;s parameters typetuple: TypeTuple!(someTypes) in the previous example.</div><div>It won&#39;t work for alias parameters, because they&#39;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(&quot;alias TypeTuple!(&quot; ~ between!(&#39;(&#39;,&#39;)&#39;,T.stringof)[1] ~ &quot;) TemplateParametersTypeTuple;&quot;);</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) == &quot;Foo&quot;);</div><div><br></div><div>assert(TemplateName!(int) == &quot;int&quot;);</div>
<div>----</div><div>*/</div><div>template TemplateName(T)</div><div>{</div><div>    enum string TemplateName = between!(&#39;!&#39;,&#39;(&#39;,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&#39;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> -&gt; test if it&#39;s a template</div><div>-&gt; extract the parameters</div>
<div>-&gt; instantiate a Bar!Parameters.</div><div><br></div><div>So, given a Bar!(int,double), it creates a Foo!(int,double). It&#39;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&#39;s OK for you.</div>
<div><br></div><div>Philippe</div><div><br></div></div>