D language template

xiaoxiao2021-03-06  41

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.

转载请注明原文地址:https://www.9cbs.com/read-55328.html

New Post(0)