www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Can't declare a "template parameter which takes anything"

reply Russell Lewis <webmaster villagersonline.com> writes:
I'd like to propose that we need a template parameter syntax which means 
"this parameter can be anything...type, alias, or value."  Currently, an 
unadorned parameter is required to be a type, and it cannot take an 
alias or value parameter.

In a perfect world, I would suggest that unadorned parameters should 
take this role, and that people who wanted templates that *only* took 
types would need to adorn their parameters with "type" (a new keyword). 
  However, that's a breaking change (few people would be affected, I 
think, but they would be affected in subtle ways) so I would be willing 
to settle for a keyword like "anything" which would declare these new 
types of parameters.



BACKGROUND

I wrote the following innocuous-seeming template because I often want to 
apply the same template to a number of parameters:

BEGIN CODE
	template template_foreach(TEMPLATE)
	{
	  alias Tuple!() template_foreach;
	}

	template template_foreach(TEMPLATE, T,TPL...)
	{
	  alias Tuple!(TEMPLATE!(T), template_foreach!(TEMPLATE, TPL))
	        template_foreach;
	}
END CODE

Looks ok to me.  But then I get errors when I try to use it in 
seemingly-simple ways:

BEGIN CODE
	template my_template(...whatever...) { ... whatever ... }

	void foo() {}

	alias template_foreach!(my_template, 1)   bar;
	alias template_foreach!(my_template, foo) baz;
END CODE

Both of those "alias" declarations give "template instance 
template_foreach!(my_template, <arg>) does not match any template 
declaraion."  Huh?

The reason for this is that the parameter T, in the 2nd 
template_foreach() declaration, is assumed that it *MUST BE A TYPE*. 
You can't pass it aliases or values.  Of course, if you rewrite 
template_foreach() to use tuples, then it works:

BEGIN CODE
	template template_foreach(TEMPLATE, TPL...)
	{
		static if(TPL.length == 0)
		   alias Tuple!() template_foreach;
		else
		   alias Tuple!(TEMPLATE!(TPL[0]),
		                template_foreach!(TEMPLATE, TPL[1..$])
		         template_foreach;
	}
END CODE

The reason that this works is that tuples can take any sort of thing as 
their elements.  But is this new template easier to read?  And will it 
make sense to a novice D programmer what is wrong?  It took me hours, if 
not days, to finally understand this.

Moreover, with the 2nd template, we lose the ability to specialize the 
template.
Mar 17 2008
next sibling parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
On Mon, 17 Mar 2008, Russell Lewis wrote:

 I'd like to propose that we need a template parameter syntax which means 
 "this parameter can be anything...type, alias, or value."  Currently, an 
 unadorned parameter is required to be a type, and it cannot take an alias or 
 value parameter.

 In a perfect world, I would suggest that unadorned parameters should take 
 this role, and that people who wanted templates that *only* took types would 
 need to adorn their parameters with "type" (a new keyword).  However, that's 
 a breaking change (few people would be affected, I think, but they would be 
 affected in subtle ways) so I would be willing to settle for a keyword like 
 "anything" which would declare these new types of parameters.



 BACKGROUND

 I wrote the following innocuous-seeming template because I often want to 
 apply the same template to a number of parameters:

 BEGIN CODE
 	template template_foreach(TEMPLATE)
 	{
 	  alias Tuple!() template_foreach;
 	}

 	template template_foreach(TEMPLATE, T,TPL...)
 	{
 	  alias Tuple!(TEMPLATE!(T), template_foreach!(TEMPLATE, TPL))
 	        template_foreach;
 	}
 END CODE

 Looks ok to me.  But then I get errors when I try to use it in 
 seemingly-simple ways:

 BEGIN CODE
 	template my_template(...whatever...) { ... whatever ... }

 	void foo() {}

 	alias template_foreach!(my_template, 1)   bar;
 	alias template_foreach!(my_template, foo) baz;
 END CODE

 Both of those "alias" declarations give "template instance 
 template_foreach!(my_template, <arg>) does not match any template 
 declaraion."  Huh?

 The reason for this is that the parameter T, in the 2nd template_foreach() 
 declaration, is assumed that it *MUST BE A TYPE*. You can't pass it aliases 
 or values.  Of course, if you rewrite template_foreach() to use tuples, then 
 it works:

 BEGIN CODE
 	template template_foreach(TEMPLATE, TPL...)
 	{
 		static if(TPL.length == 0)
 		   alias Tuple!() template_foreach;
 		else
 		   alias Tuple!(TEMPLATE!(TPL[0]),
 		                template_foreach!(TEMPLATE, TPL[1..$])
 		         template_foreach;
 	}
 END CODE

 The reason that this works is that tuples can take any sort of thing as their 
 elements.  But is this new template easier to read?  And will it make sense 
 to a novice D programmer what is wrong?  It took me hours, if not days, to 
 finally understand this.

I don't know what kind of plans Walter has, but I'm hoping that the macros could be used when arbitrary arguments are needed - they could match different kinds of AST subtrees. It would still make perfectly sense to use templates when operating with types. If the example above only creates new parametrized types, you could make it more readable by using a compile time map metafunction. But yea, I agree having arguments of type 'type' is a bit problematic. It might be a better idea to make it a special case just like values, aliases, and tuples are, and having a "tuple of size 1" as a default.
Mar 17 2008
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Russell Lewis" wrote
 I'd like to propose that we need a template parameter syntax which means 
 "this parameter can be anything...type, alias, or value."  Currently, an 
 unadorned parameter is required to be a type, and it cannot take an alias 
 or value parameter.

Have you tried alias parameters? template template_foreach(alias T) ... This allows any symbol to be given (http://www.digitalmars.com/d/1.0/template.html#TemplateAliasParameter) I'm not sure if it works for literals though. -Steve
Mar 17 2008
parent =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
On Mon, 17 Mar 2008, Steven Schveighoffer wrote:

 "Russell Lewis" wrote
 I'd like to propose that we need a template parameter syntax which means
 "this parameter can be anything...type, alias, or value."  Currently, an
 unadorned parameter is required to be a type, and it cannot take an alias
 or value parameter.

Have you tried alias parameters? template template_foreach(alias T) ... This allows any symbol to be given (http://www.digitalmars.com/d/1.0/template.html#TemplateAliasParameter) I'm not sure if it works for literals though.

It doesn't match types (unless they have a symbol, e.g. typedefs have) or values (except blocks and possibly some other special cases).
Mar 17 2008