<div class="gmail_quote">On Sat, Jul 31, 2010 at 21:17, Lutger <span dir="ltr">&lt;<a href="mailto:lutger.blijdestijn@gmail.com">lutger.blijdestijn@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5">Jason Spencer wrote:<br>
<br>
&gt; == Quote from Philippe Sigaud (<a href="mailto:philippe.sigaud@gmail.com">philippe.sigaud@gmail.com</a>)&#39;s article<br>
&gt;&gt; --0016e6d58a039d35e2048c9aa7e2<br>
&gt;&gt;<br>
&gt;&gt; I thought they could only be symbols. That is, an alias is a &#39;link&#39;,<br>
&gt; a sort<br>
&gt;&gt; of pointer to a symbol: a template name, a module name, a function<br>
&gt;&gt; name, etc.<br>
&gt;<br>
&gt; Whatever confidence you inspired by removing type from the list is<br>
&gt; quickly lost and more when you add module name--I hadn&#39;t thought of<br>
&gt; that! :)<br></div></div></blockquote><div><br></div><div>I discovered it by error, IIRC. That and the fact that template-like statements like</div><div><br></div><div>auto members = __traits(allMembers, std.stdio);</div>
<div><br></div><div>work.  Try it, print the result. Though I do not know what to do with it :)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div>
<div class="h5">
&gt;<br>
&gt;<br>
&gt;&gt; Wisdom, I don&#39;t know, as I still feel like I&#39;m exploring things. But<br>
&gt;&gt; template constraints are there to limit what you can instantiate.<br>
&gt;&gt; ...<br>
&gt;&gt; Say I have a template that takes an alias, fun, and a type, T.<br>
&gt;&gt; fun is supposed to be a function, but in fact why limit it to that?<br>
&gt;&gt; What I need is for foo to be callable with a T. So let&#39;s test for<br>
&gt;&gt; that:<br>
&gt;&gt; auto doSomething(alias fun, T)(T t)<br>
&gt;&gt; if (is(typeof( fun(T.init) )))<br>
&gt;&gt; {<br>
&gt;&gt; // now that I&#39;m here, I can freely use fun as a callable on any T<br>
&gt;&gt;  auto result = fun(t);<br>
&gt;&gt; // ...<br>
&gt;&gt; }<br>
&gt;<br>
&gt; I understand this example, and (most of) the mechanics of constraints.<br>
&gt; What I&#39;m not so sure about is the recommended practice around their<br>
&gt; use.  I see lot&#39;s of code that doesn&#39;t check those things.  Suppose<br>
&gt; you left off the constraint and did:<br>
&gt;<br>
&gt; class Foo(U){}<br>
&gt; doSomething!(Foo, int)(3)<br>
&gt;<br>
&gt; it seems like there&#39;s a good chance you could get:<br>
&gt;<br>
&gt; auto result = Foo!(int);  // type inferred from 3<br>
&gt;<br>
&gt; (since this doesn&#39;t actually work like I&#39;m saying, please conveniently<br>
&gt; imagine a similar case that does. :)<br>
<br>
</div></div>Sure, but that would be quite a gotcha since you went from calling something to<br>
merely instantiating a template. Perhaps there are such gotcha&#39;s, I am not aware<br>
of them.<br></blockquote><div><br></div><div>You can test for the alias to be a function (is(typeof(a) == function)), a delegate, or you can test for the presence of an opCall operator (the &#39;()&#39; operator), with __traits(hasMember, alias, &quot;opCall&quot;)</div>
<div>I think there should be a isCallable trait in Phobos...</div><div>But in the opCall case, the gotcha is the class templates are not classes. Only instantiated classes are really classes.</div><div>That is, given</div>
<div><br></div><div>class C(T)</div><div>{</div><div> T t;</div><div> T opCall(T u) { return t;}</div><div>}</div><div><br></div><div>__traits(hasMember, C, &quot;opCall&quot;) will answer &#39;false&#39;. That&#39;s normal, since C is not a class, but a template, of type void.</div>
<div>__traits(hasMember, C!int, &quot;opCall&quot;) will answer &#39;true&#39;.</div><div><br></div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<div class="im"><br>
&gt; Even with your constraint, I&#39;m not sure I feel any more comfortable.<br>
&gt; If it compiles in the body of doSomething, it will compile in the<br>
&gt; constraint--not sure I&#39;ve added any value.<br>
<br>
</div>Perhaps not in this case, but:<br>
- constraints add documentation, such as isInputRange!T or IsCallable!fun<br>
- you can add a constraint that may not be statically checked inside the body of<br>
the template. This way you can still reject template parameters considered to be<br>
invalid even if the template body *could* be instantiated with them.<br></blockquote><div><br></div><div>I never thought of that.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

- a constraint is a nice place to add better compiler error messages<br></blockquote><div><br></div><div>Except the compiler just say it cannot instantiate the template NameWithConstraints. </div><div><br></div><div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">
&gt; So how do you sleep at night not knowing if there&#39;s some funky syntax<br>
&gt; on somebody&#39;s template-that-takes-a-template which, when combined with<br>
&gt; some inference, might look like your function call on a value param?<br>
&gt; My initial reaction is to specify the hell out of the constraints, but<br>
&gt; I couldn&#39;t beat the feeling I was going overboard.  I suspect that<br>
&gt; most people rely on the fact that most improper calls won&#39;t compile.<br></div></blockquote><div><br></div><div>Yes. </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">
&gt; Maybe I&#39;m still too new to the syntax to have a good feel for what<br>
&gt; will get caught, and what could interpreted by the compiler in<br>
&gt; multiple ways depending on the actual arguments.<br></div></blockquote><div><br></div><div>I have nothing against long and well-documented constraints. I feel we are not using them as much as we could. With things like staticMap and such, you can do a lot!</div>
<div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">
&gt;<br>
&gt; So, do folks write constraints to ensure that modules don&#39;t get passed<br>
&gt; to their templates?  :)<br>
&gt;<br>
&gt; Jason<br>
<br>
</div>Why not? As long as your module does the right thing, it may be used to<br>
instantiate my template :)<br>
</blockquote></div><br><div>You can try to define an isTemplate template, and a isModule template :-)</div><div><br></div><div>Look at this:</div><div><br></div><div><div>T foo(T)(T t) { return t;}</div><div><br></div><div>
class C(T)</div><div>{</div><div>    T t;</div><div>    T opCall(T u) { return t;}</div><div>}</div><div><br></div><div>template Describe(alias a)</div><div>{</div><div>    enum string Name = a.stringof;</div><div>    enum string Ident = __traits(identifier, a);</div>
<div>}</div><div><br></div><div>void main()</div><div>{</div><div>    writeln(Describe!(foo).Name); // foo(T)</div><div>    writeln(Describe!(foo).Ident); // foo</div><div>    writeln(Describe!(C).Name); // C(T)</div><div>
    writeln(Describe!(C).Ident); // C</div><div>    writeln(Describe!(C!int).Name); // C (really, I thought that would be C!(int). I remember devising a way to extract the types from a template</div><div>    writeln(Describe!(C!int).Ident); // C</div>
<div><br></div><div>    writeln(Describe!(Describe).Name); // Calling it on itself!  Describe(alias a)</div><div>    writeln(Describe!(Describe).Ident); // Describe</div><div><br></div><div>    writeln(Describe!(std.stdio).Name); // module stdio   Strange, no std. in sight.</div>
<div>    writeln(Describe!(std.stdio).Ident); // stdio</div></div><div>}</div><div><br></div><div>So, inside a template a.stringof gives &quot;module a&quot; if a is a module, except it seems to cut anything before a dot. I do not like relying on .stringof, because it&#39;s undocumented and not always perfectly coherent. But a pragmatic implementation of isModule could be:</div>
<div><br></div><div>template isModule(alias symbol)</div><div>{</div><div>  enum bool isModule = (symbol.stringof[0..7] == &quot;module &quot;);</div><div>}</div><div><br></div><div><br></div><div>:-)</div><div><br></div>
<div>Philippe</div><div><br></div>