D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 2640 - Improve usability of the "inner name trick"
Summary: Improve usability of the "inner name trick"
Status: RESOLVED DUPLICATE of issue 4675
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86 Linux
: P2 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-02-01 15:19 UTC by Andrei Alexandrescu
Modified: 2015-06-09 01:31 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Andrei Alexandrescu 2009-02-01 15:19:30 UTC
The "inner name trick" consists of a template only defining a symbol of the same name as itself. Then, any instantiation of the template will in fact shunt to the defined inner symbol. Example:

template A(T) { alias T[] A; }

Using e.g. A!(int) will be entirely synonymous with int[].

This is a hugely useful feature that is bound to be heavily used in a variety of templated code. Unfortunately, there is a limitation - the template is disallowed from defining any symbol. The motivation of the limitation is that the shunting mechanism would in fact disallow access to that member.

The fallout of this is that many nontrivial templates follow the pattern:

template Widget(T)
{
    alias WidgetImpl!(T).Result Widget;
}

template WidgetImpl(T)
{
    ... actual implementation defining several private symbols ...
    alias ...something... Result;
}

That way users have the convenience of using Widget!(T) instead of Widget!(T).Result, and the implementor has the ability to define nontrivial template code that defines and uses several symbols towards computing the desired result. The obvious cost is that extra code must be written.

I'd like to find a solution to this because the pattern is starting to creep really bad in Phobos. One idea is to allow a template using the inner name trick to define any number of symbols inside. As long as those symbols are accessed USING UNQUALIFIED ACCESS, they are looked up normally. That means that inside the template itself, defining "temporary" aliases is fair game. As soon as the template is "closed", the user can't have access to the inner symbols.

Example:

template A(T) 
{
    alias T X;   // define inner symbol X
    alias X[] A; // use of UNQUALIFIED X ok
    alias A!(int).X Y; // error: type int[] does not define X
}

So, in short: the template can define and use symbols at its leisure. Use of the symbols follow the normal rule: first in the template's scope, then outside. But if the template aliases itself using the inner name trick, then the shunting is done prior to looking the name up (as is done today).
Comment 1 Jarrett Billingsley 2009-02-01 16:29:18 UTC
Agreed 100%.  I think I even posted a suggestion to this effect years ago on the digitalmars.D board?  I forget.
Comment 2 Koroskin Denis 2009-02-01 17:13:02 UTC
Yeah, I have proposed that, too. I suggested marking all internal temporary aliases as private for that purpose:

template WidgetImpl(T)
{
    private alias ...something_complex... Tmp; // not visible from outside
    alias ...something_else... WidgetImpl; // public
}
Comment 3 Martin Nowak 2012-01-22 01:37:35 UTC

*** This issue has been marked as a duplicate of issue 4675 ***