www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - About template template arguments syntax

reply bearophile <bearophileHUGS lycos.com> writes:
This little program is a reduction of code recently shown around here:


template Spam(T, alias P) { enum Spam = P!T; }
template Foo(T, Preds...) {
    enum bool Foo = Spam!(T, Preds[0]);
}
template Bar(T) { enum Bar = true; }
static assert(Foo!(int, Bar));
void main() {}


Do you know why the P argument of Spam needs "alias" before?
The type tuple Preds of Foo doesn't need an "alias" before.

Isn't it possible to remove the need to use such "alias" for template template
arguments in D? (This is a question I've had to ask since a lot of time).

Bye and thank you,
bearophile
Oct 01 2011
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Oct 2, 2011 at 04:20, bearophile <bearophileHUGS lycos.com> wrote:
 This little program is a reduction of code recently shown around here:


 template Spam(T, alias P) { enum Spam =3D P!T; }
 template Foo(T, Preds...) {
 =C2=A0 =C2=A0enum bool Foo =3D Spam!(T, Preds[0]);
 }
 template Bar(T) { enum Bar =3D true; }
 static assert(Foo!(int, Bar));
 void main() {}


 Do you know why the P argument of Spam needs "alias" before?
Because P is a template name, not a type. 'Bar' is not a type, it's a template: a blueprint for producing code. Symbols, can only be manipulated in D through aliases (though it's cool they can be manipulated at all!)
 The type tuple Preds of Foo doesn't need an "alias" before.
Because template parameters tuples are mongrel constructs, able to store both types and aliases. Tuples members are automatically aliases, if you will.
 Isn't it possible to remove the need to use such "alias" for template tem=
plate arguments in D? (This is a question I've had to ask since a lot of ti= me). That sure would simplify some code, particularly when you write generic code that deals with both types and symbols (Yes, it happens). I don't know if it's possible and/or if it's a good idea or not. Philippe
Oct 02 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Philippe Sigaud:

 Because P is a template name, not a type. 'Bar' is not a type, it's a
 template: a blueprint for producing code. Symbols, can only be
 manipulated in D through aliases (though it's cool they can be
 manipulated at all!)
So the need to add "alias" there allows some static typing, to tell apart names or names and symbols. Thank you, bearophile
Oct 02 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/02/2011 02:44 PM, Philippe Sigaud wrote:
 On Sun, Oct 2, 2011 at 04:20, bearophile<bearophileHUGS lycos.com>  wrote:
 This little program is a reduction of code recently shown around here:


 template Spam(T, alias P) { enum Spam = P!T; }
 template Foo(T, Preds...) {
     enum bool Foo = Spam!(T, Preds[0]);
 }
 template Bar(T) { enum Bar = true; }
 static assert(Foo!(int, Bar));
 void main() {}


 Do you know why the P argument of Spam needs "alias" before?
Because P is a template name, not a type. 'Bar' is not a type, it's a template: a blueprint for producing code. Symbols, can only be manipulated in D through aliases (though it's cool they can be manipulated at all!)
 The type tuple Preds of Foo doesn't need an "alias" before.
Because template parameters tuples are mongrel constructs, able to store both types and aliases. Tuples members are automatically aliases, if you will.
 Isn't it possible to remove the need to use such "alias" for template template
arguments in D? (This is a question I've had to ask since a lot of time).
That sure would simplify some code, particularly when you write generic code that deals with both types and symbols (Yes, it happens). I don't know if it's possible and/or if it's a good idea or not.
Types are symbols, so just using alias template arguments works.
Oct 02 2011
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Oct 2, 2011 at 19:12, Timon Gehr <timon.gehr gmx.ch> wrote:

 Types are symbols, so just using alias template arguments works.
Hmm, no. template isSymbol(alias a) { enum isSymbol = true; } void main() { enum a = isSymbol!int; } Error: template instance isSymbol!(int) does not match template declaration isSymbol(alias a)
Oct 02 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 10/02/2011 08:48 PM, Philippe Sigaud wrote:
 On Sun, Oct 2, 2011 at 19:12, Timon Gehr<timon.gehr gmx.ch>  wrote:

 Types are symbols, so just using alias template arguments works.
Hmm, no. template isSymbol(alias a) { enum isSymbol = true; } void main() { enum a = isSymbol!int; } Error: template instance isSymbol!(int) does not match template declaration isSymbol(alias a)
template isSymbol(alias T){ enum isSymbol=true; } template ID(T){alias T x;} void main(){ bool mooh=isSymbol!(ID!int); } Well, that should be fixed.
Oct 02 2011
parent reply David Nadlinger <see klickverbot.at> writes:
On 10/2/11 9:19 PM, Timon Gehr wrote:
 template isSymbol(alias T){
 enum isSymbol=true;
 }

 template ID(T){alias T x;}

 void main(){
 bool mooh=isSymbol!(ID!int);
 }

 Well, that should be fixed.
By the way, the issue here is the builtin primitive types are not considered symbols, user-defined types are matched by alias. David
Oct 02 2011
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Sun, Oct 2, 2011 at 23:25, David Nadlinger <see klickverbot.at> wrote:

 By the way, the issue here is the builtin primitive types are not considered
 symbols, user-defined types are matched by alias.
That's because user-defined types have a name, I guess. So alias catches the name, not the underlying types (if that makes sense). Hmm, I wonder what happens with anonymous user-defined types. I guess the compiler has an internal name for them, like for anonymous functions. Philippe
Oct 02 2011