Template D For generic programming through template.
Template declaration is defined as:
Template statement:
Template template flag (list of template parameters)
{Declaration definition}
Template marker:
Marker
Template parameter list
Template parameters
Template parameters, template parameter list
Template parameters:
Type parameters
Value parameters
Alias parameter
Template type parameters:
Marker
Signature template type parameter specialization
Flag template type parameter default value
Flags Template Type Parameter Charge Template Type Parameter Default
Template type parameter specialization:
: Types of
Template type parameter default value:
= Type
Template value parameter:
statement
Declare template value parameter test
Declare template value parameter default value
Disclaimer template value parameter test template value parameter default value
Template value parameter test:
: Conditional expression
Template value parameter default value:
= Conditional expression
Template alias parameter:
Alias logo
Alias flag template alias parameter default value
Template alias parameter default value:
= Type
TemplatedEclaration:
Template TemplateIdentifier (TemplateParameterList)
{Decldefs}
TemplateIdentifier:
Identifier
TemplateParameterList
TemplateParameter
TemplateParameter, TemplateParameterList
TemplateParameter:
TypeParameter
ValueParameter
AliaSparameter
TemplateTypeParameter:
Identifier
Identifier TemplattypeParameterspecialization
Identifier TemplateTypeParameterDefault
Identifier TemplateTypeParameterspeParameterDefault
TemplateTypeParameterspecialization:
: Type
TemplateTypeParameterDefault:
= Type
TemplateValueParameter:
Declaration
Declaration TemplateValueParameterspecialization
Declaration TemplateValueParameterDefault
Declaration TemplateValueParameterspecialization TemplateValueParameterDefault
TemplateValueParameterspecialization:
: ConditionaLexpression
TemplateValueParameterDefault:
= ConditionaExpression
TemplateAliasParameter:
Alias Identifier
Alias Identifier TemplateAliasParameterDefault
TemplateAliasParameterDefault:
= Type
Whether the template is finalized,
The process body of the template declaration must be correct on the grammatical. Semantic analysis is delayed when the template is instantiated. Templates have their own scope, and the template process can include classes, structures, types, enumerations, variables, functions, or other templates.
Template parameters can be type, value, or symbol. You can use any type. Value parameters must be an integer type, they must be parsed to integer constants when they are specifically. The symbol can be any non-local symbol.
Template Parameter Characterization The value or type of the template parameter can be accepted by the template parameter.
Template parameters defaults when not providing template parameters.
The instances of the template instantiation template are defined as:
Template example:
Template marker! (Template parameter list)
Template parameter list:
Template parameter template parameter, template parameter list
Template parameters:
Types of
Assignment expression
symbol
TemplateInstance:
TemplateIndifer! (TemplateargumentList)
TemplateargumentList:
Templateargument
Templateargument, TemplateargumentListListListListListListList
Templateargument:
Type
AssignExpression
Symbol
Once instantiated, the declaration in the template, called a template member, is located
TemplateInstance scope:
Template Tfoo (t) {alias t * t;}
...
Tfoo! (Int) .t x; // declaration X is int * type
Template instantiation can have an alias:
Template Tfoo (t) {alias t * t;}
Alias Tfoo! (int) ABC;
abc.t x; // Declaration X is int * type
One
Template statement has the same
Multiple instances of the template parameter list will reference the same instance. E.g:
Template TfOO (T) {T f;
Alias tfoo (int) a;
Alias Tfoo (int) b;
...
A.f = 3;
Assert (B.F == 3); // a and b reference the same TFOO instance
even if
Template instances are located in different modules, which is also true.
If you declare a template with multiple identical template markers, and their parameters are different or different by different specialties, then they are different.
For example, a simple generic replication function can be this:
Template TCOPY (T)
{
Void Copy (Out T To, T from)
{
TO = from;
}
}
Before using the template, you must use the specific type to instantiate:
INT I;
Tcopy! (Int) .copy (i, 3);
Installation scope
Template instance is always declared
The scope of the template declaration is executed, and the other declared template parameters are viewed as the alias of the types they launched.
E.g:
-------- Module A ---------
Template Tfoo (T) {Void Bar () {func ();}}
-------- Module B ---------
Import a;
Void func () {}
Alias tfoo! (int) f; // error: FUNC is not defined within module A
as well as:
-------- Module A ---------
Template Tfoo (T) {Void Bar () {Func (1);}}
Void func (double d) {}
-------- Module B ---------
Import a;
Void Func (INT I) {}
Alias Tfoo! (int) f;
...
f.bar (); // will call A.Func (double)
Template parameters and defaults will be
The scope of the template declaration.
The parameter derived uses the method of comparing the corresponding template parameters and template argument, the type of template parameters in the template instance is pushed out.
For each template parameter, apply the rules by following the order below until the type of each parameter is pushed out:
If the parameter does not specify a specialization, the type of parameter is set to the specified template. If the type transition is dependent on a type parameter, the type of this parameter is set to the type corresponding to the type of arguments. If there is a type parameter after all types of parameters are not assigned, they are assigned to templates in the same location in the template parameter list. If you apply the above rules, you can't do the unique type of each template parameter, it is considered an error. For example: Template Tfoo (T) {}
Alias Tfoo! (int) foo1; // (1) T is derived as int
Alias Tfoo! (char *) foo2; // (1) T is derived as char *
Template Tfoo (T: t *) {}
Alias Tfoo! (char *) foo3; // (2) T is derived as char
Template TBAR (D, U: D []) {}
Alias TBAR! (int, int, int, int, "D is derived to int, u is derived as int []
Alias TBAR! (char, int []) bar2; // (4) error, D is both char and int
Template TBAR (D: E *, E) {}
Alias TBAR! (int *, int) bar3; // (1) e is int
// (3) D is int *
When considering matching, a class is considered to match any parent class or interface:
Class a {}
Class B: a {}
Template TFOO (T: a) {}
Alias tfoo! (b) foo4; // (3) T is B
Template TBAR (T: U *, U: a) {}
Alias TBAR! (B *, b) foo5; // (2) T is b *
// (3) u is B
In the template example of the value parameter, specify a value parameter for 10:
Template foo (u: int, int T: 10)
{
U x = T;
}
void main ()
{
Assert (foo! (int, 10) .x == 10);
}
The Charge Template can specify a ":" and a special type of tests after the template parameters to use some specified real parameters type. E.g:
Template Tfoo (T) {...} // # 1
Template Tfoo (T: t []) {...} // # 2
Template Tfoo (T: Char) {...} // # 3
Template TfOO (T, U, V) {...} // # 4
Alias tfoo! (int) foo1; // instantified # 1
Alias Tfoo! (Double []) foo2; // Instantian # 2, where T is Double
Alias Tfoo! (char) foo3; // instantified # 3
Alias Tfoo! (char, int) fooe; / / error, unquestionable
Alias Tfoo! (CHAR, INT, INT) Foo4; // Instantified # 4
When the template is instantiated, the match is selected.
The template parameter list is the highest type template. Deciding that the way that template is more specialized is the same as C processing preference rules. If the result is ambiguous, it is an error.
Alias parameter alias parameters allow templates to use any D symbol parameterization, including global name, type name, template name, and template instance name. Local names may not be an alias parameter. This is a super-collection of the Template as a template parameter in C .
Global name INT X;
Template foo (alias x)
{
Static Int * P = & x;
}
Void test ()
{
Alias foo! (x) bar;
* bar.p = 3; // Set X is 3
Int Y;
Alias foo! (y) ABC; / / error, Y is a local name
} Type name Class Foo
{
Static int P;
}
Template Bar (Alias T)
{
Alias T.P Q;
}
Void test ()
{
Alias bar! (foo) bar;
Bar.q = 3; // Set foo.p to 3
} Module name import std.string;
Template foo (alias x)
{
Alias X.toString Y;
}
Void test ()
{
Alias foo! (std.string) bar;
Bar.y (3); // Call std.string.toString (3)
} Template name INT X;
Template foo (alias x)
{
Static Int * P = & x;
}
Template Bar (Alias T)
{
Alias T! (x) ABC;
}
Void test ()
{
Alias bar! (foo) bar;
* bar.abc.p = 3; // Set X is 3
} Template alias INT X;
Template foo (alias x)
{
Static Int * P = & x;
}
Template Bar (Alias T)
{
Alias T.P Q;
}
Void test ()
{
Alias foo! (x) foo;
Alias bar! (foo) bar;
* bar.q = 3; // Set X is 3
}
Template parameters default values The template parameters (from the rightmost one of the left consecutive parameters) can have default:
Template foo (t, u = int) {...}
Foo! (Uint, long); // Instantiation: T is UINT, U is Long
Foo! (Uint); // Installation: T is uint, u is int
Template foo (t, u = t *) {...}
Foo! (Uint); // Instantiation: T is uint, u is uint *
Implicit Template Properties If there are only one member, and this member and template are as the same name, this member is considered a template instance:
Template foo (t)
{
T foo; // Declare the variable foo as type T
}
Void test ()
{
Foo! (Int) = 6; // Replace foo! (Int) .foo
}
Class template
Class template declaration:
Class flag (template parameter list) [parent class {, interface class}] class procedure
ClassTemplatedEclaration:
Class Identifier (TemplationParameterList) [Superclass {, InterfaceClass}] ClassBody
If a template is declared and only declares a member, and that member is a class with the same name with the template:
Template Bar (T)
{
Class Bar
{
T member;
}
}
Then the following declaration semantics is called
Class template declaration:
Class Bar (T)
{
T member;
}
The recursive template can combine the various characteristics of the template to generate some interesting effects, such as evaluating the non-plain function when compiling. For example, you can write a calculated stage: Template Factorial (INT N: 1)
{
ENUM {Factorial = 1}
}
Template Factorial (Int n)
{
// Note: '.' Used to find templates in the global scope rather than enumeration
Enum {factory = n * .factorial! (N-1)}
}
Void test ()
{
Printf ("% D / N", Factorial! (4)); // Print 24
}
Limit templates cannot be used to add non-static members or functions to classes. E.g:
Class foo
{
Template TBAR (T)
{
T xx; // error
INT func (t) {...} // error
Static t yy; // ok
Static int func (t t, int y) {...} // ok
}
}
You cannot declare the template within the function.