alias = compile-time variants?

Philippe Sigaud philippe.sigaud at gmail.com
Sun Aug 1 13:43:53 PDT 2010


On Sat, Jul 31, 2010 at 21:17, Lutger <lutger.blijdestijn at gmail.com> wrote:

> Jason Spencer wrote:
>
> > == Quote from Philippe Sigaud (philippe.sigaud at gmail.com)'s article
> >> --0016e6d58a039d35e2048c9aa7e2
> >>
> >> I thought they could only be symbols. That is, an alias is a 'link',
> > a sort
> >> of pointer to a symbol: a template name, a module name, a function
> >> name, etc.
> >
> > Whatever confidence you inspired by removing type from the list is
> > quickly lost and more when you add module name--I hadn't thought of
> > that! :)
>

I discovered it by error, IIRC. That and the fact that template-like
statements like

auto members = __traits(allMembers, std.stdio);

work.  Try it, print the result. Though I do not know what to do with it :)


> >
> >
> >> Wisdom, I don't know, as I still feel like I'm exploring things. But
> >> template constraints are there to limit what you can instantiate.
> >> ...
> >> Say I have a template that takes an alias, fun, and a type, T.
> >> fun is supposed to be a function, but in fact why limit it to that?
> >> What I need is for foo to be callable with a T. So let's test for
> >> that:
> >> auto doSomething(alias fun, T)(T t)
> >> if (is(typeof( fun(T.init) )))
> >> {
> >> // now that I'm here, I can freely use fun as a callable on any T
> >>  auto result = fun(t);
> >> // ...
> >> }
> >
> > I understand this example, and (most of) the mechanics of constraints.
> > What I'm not so sure about is the recommended practice around their
> > use.  I see lot's of code that doesn't check those things.  Suppose
> > you left off the constraint and did:
> >
> > class Foo(U){}
> > doSomething!(Foo, int)(3)
> >
> > it seems like there's a good chance you could get:
> >
> > auto result = Foo!(int);  // type inferred from 3
> >
> > (since this doesn't actually work like I'm saying, please conveniently
> > imagine a similar case that does. :)
>
> Sure, but that would be quite a gotcha since you went from calling
> something to
> merely instantiating a template. Perhaps there are such gotcha's, I am not
> aware
> of them.
>

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 '()'
operator), with __traits(hasMember, alias, "opCall")
I think there should be a isCallable trait in Phobos...
But in the opCall case, the gotcha is the class templates are not classes.
Only instantiated classes are really classes.
That is, given

class C(T)
{
 T t;
 T opCall(T u) { return t;}
}

__traits(hasMember, C, "opCall") will answer 'false'. That's normal, since C
is not a class, but a template, of type void.
__traits(hasMember, C!int, "opCall") will answer 'true'.





>
> > Even with your constraint, I'm not sure I feel any more comfortable.
> > If it compiles in the body of doSomething, it will compile in the
> > constraint--not sure I've added any value.
>
> Perhaps not in this case, but:
> - constraints add documentation, such as isInputRange!T or IsCallable!fun
> - you can add a constraint that may not be statically checked inside the
> body of
> the template. This way you can still reject template parameters considered
> to be
> invalid even if the template body *could* be instantiated with them.
>

I never thought of that.


> - a constraint is a nice place to add better compiler error messages
>

Except the compiler just say it cannot instantiate the template
NameWithConstraints.



> > So how do you sleep at night not knowing if there's some funky syntax
> > on somebody's template-that-takes-a-template which, when combined with
> > some inference, might look like your function call on a value param?
> > My initial reaction is to specify the hell out of the constraints, but
> > I couldn't beat the feeling I was going overboard.  I suspect that
> > most people rely on the fact that most improper calls won't compile.
>

Yes.


> > Maybe I'm still too new to the syntax to have a good feel for what
> > will get caught, and what could interpreted by the compiler in
> > multiple ways depending on the actual arguments.
>

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!



> >
> > So, do folks write constraints to ensure that modules don't get passed
> > to their templates?  :)
> >
> > Jason
>
> Why not? As long as your module does the right thing, it may be used to
> instantiate my template :)
>

You can try to define an isTemplate template, and a isModule template :-)

Look at this:

T foo(T)(T t) { return t;}

class C(T)
{
    T t;
    T opCall(T u) { return t;}
}

template Describe(alias a)
{
    enum string Name = a.stringof;
    enum string Ident = __traits(identifier, a);
}

void main()
{
    writeln(Describe!(foo).Name); // foo(T)
    writeln(Describe!(foo).Ident); // foo
    writeln(Describe!(C).Name); // C(T)
    writeln(Describe!(C).Ident); // C
    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
    writeln(Describe!(C!int).Ident); // C

    writeln(Describe!(Describe).Name); // Calling it on itself!
 Describe(alias a)
    writeln(Describe!(Describe).Ident); // Describe

    writeln(Describe!(std.stdio).Name); // module stdio   Strange, no std.
in sight.
    writeln(Describe!(std.stdio).Ident); // stdio
}

So, inside a template a.stringof gives "module a" if a is a module, except
it seems to cut anything before a dot. I do not like relying on .stringof,
because it's undocumented and not always perfectly coherent. But a pragmatic
implementation of isModule could be:

template isModule(alias symbol)
{
  enum bool isModule = (symbol.stringof[0..7] == "module ");
}


:-)

Philippe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20100801/4ced5250/attachment.html>


More information about the Digitalmars-d-learn mailing list