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

spir denis.spir at gmail.com
Tue Mar 8 11:20:40 PST 2011


On 03/08/2011 06:20 PM, Steven Schveighoffer wrote:
> 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

I don't share your enthusiasm, Steven, for this feature (which I did not know). 
In fact, I tend to consider it a mis-feature. Yet another syntactic 
special-case for special cases in the language. In this case, there are even 3 
ways to write the same thing:
	CheckedInt
	CheckedInt!N
	CheckedInt!(N)
And note these variants are low-level ones, morphological rather than syntactic 
properly speaking.

Denis
-- 
_________________
vita es estrany
spir.wikidot.com



More information about the Digitalmars-d-learn mailing list