Templated struct doesn't need the parameterized type in return type definitions?

Steven Schveighoffer schveiguy at yahoo.com
Tue Mar 8 09:20:29 PST 2011


On Tue, 08 Mar 2011 12:06:08 -0500, Andrej Mitrovic <none at none.none> wrote:

> import std.stdio;
> import std.traits;
> import std.exception;
>
> struct CheckedInt(N) if (isIntegral!N)
> {
>     private N value;
>    ref CheckedInt opUnary(string op)() if (op == "++")
>     {
>         enforce(value != value.max);
>         ++value;
>         return this;
>     }
>    this(N _value)
>     {
>         value = _value;
>     }
> }
>
> I didn't know you could define a return type of a templated struct  
> without defining the type it is parameterized on. I mean this line:
>
> ref CheckedInt opUnary(string op)() if (op == "++")
>
> I thought for sure I always had to write the parameterized type like so:
>
> ref CheckedInt!(N) opUnary(string op)() if (op == "++")
>
> So I guess this really isn't a question but more of a "oh, I didn't know  
> you could do that". In fact I rarely see this kind of code in Phobos,  
> most of the time the parameterized type is specified in these types of  
> cases. Is this feature described somewhere, because I must have missed  
> it if it is?

It is described, but not directly.

Look on this page:

http://www.digitalmars.com/d/2.0/template.html

   From there we have these two descriptions:

------------------------

If a template has exactly one member in it, and the name of that member is
the same as the template name, that member is assumed to be referred to in
a template instantiation:
template Foo(T)
{
       T Foo;	// declare variable Foo of type T
}

void test()
{
       Foo!(int) = 6;	// instead of Foo!(int).Foo
}

------------------------

If a template declares exactly one member, and that member is a class with
the same name as the template:
template Bar(T)
{
       class Bar
       {
	T member;
       }
}

then the semantic equivalent, called a ClassTemplateDeclaration can be
written as:
class Bar(T)
{
       T member;
}

------------------------

Also note that structs have the same description.

So if you think about it, your code is equivalent to:

template CheckedInt(N) if(isIntegral!N)
{
    struct CheckedInt
    {
       ...
    }
}

If you look at it this way, it makes complete sense that within the struct  
that's within the template, the struct can refer to itself without the  
specific instantiation parameters.

I think this should really be laid out properly in the docs.  I discovered  
this "trick" while writing dcollections by accident and thought it so  
awesome that I changed all my code which self-returned (quite a bit).

-Steve


More information about the Digitalmars-d-learn mailing list