Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.


Defines TemplateDeclaration, TemplateInstance and a few utilities
This modules holds the two main template types: TemplateDeclaration, which is the user-provided declaration of a template, and TemplateInstance, which is an instance of a TemplateDeclaration with specific arguments.

Template Parameter Additionally, the classes for template parameters are defined in this module. The base class, TemplateParameter, is inherited by:

  • TemplateTypeParameter
  • TemplateThisParameter
  • TemplateValueParameter
  • TemplateAliasParameter
  • TemplateTupleParameter

Templates semantic The start of the template instantiation process looks like this:

  • A TypeInstance or TypeIdentifier is encountered. TypeInstance have a bang (e.g. Foo!(arg)) while TypeIdentifier don't.
  • A TemplateInstance is instantiated
  • Semantic is run on the TemplateInstance (see dmd.dsymbolsem)
  • The TemplateInstance search for its TemplateDeclaration, runs semantic on the template arguments and deduce the best match among the possible overloads.
  • The TemplateInstance search for existing instances with the same arguments, and uses it if found.
  • Otherwise, the rest of semantic is run on the TemplateInstance.


Source dtemplate.d

pure nothrow @nogc @safe inout(Expression) isExpression(inout RootObject o);
These functions substitute for dynamic_cast. dynamic_cast does not work on earlier versions of gcc.
pure nothrow @nogc @safe bool isError(const RootObject o);
Is this Object an error?
pure nothrow @nogc @safe bool arrayObjectIsError(const ref Objects args);
Are any of the Objects an error?
pure nothrow @nogc @safe inout(Type) getType(inout RootObject o);
Try to get arg as a type.
Dsymbol getDsymbol(RootObject oarg);
If oarg represents a Dsymbol, return that Dsymbol
RootObject oarg argument to check
Dsymbol if a symbol, null if not
bool arrayObjectMatch(ref Objects oa1, ref Objects oa2);
Match an array of them.
class TemplateDeclaration: dmd.dsymbol.ScopeDsymbol;
[mixin] template Identifier (parameters) [Constraint]
bool isTrivialAliasSeq;
matches pattern template AliasSeq(T...) { alias AliasSeq = T; }
bool isTrivialAlias;
matches pattern template Alias(T) { alias Alias = qualifiers(T); }
bool deprecated_;
this template declaration is deprecated
Expression lastConstraint;
the constraint after the last failed evaluation
Array!Expression lastConstraintNegs;
its negative parts
Objects* lastConstraintTiargs;
template instance arguments for lastConstraint
bool overloadInsert(Dsymbol s);
Overload existing TemplateDeclaration 'this' with the new one 's'.
Dsymbol s symbol to be inserted

Return true if successful; i.e. no conflict.

const(char)* getConstraintEvalError(ref const(char)* tip);
Destructively get the error message from the last constraint evaluation
const(char)* tip tip to show after printing all overloads
TemplateInstance findExistingInstance(TemplateInstance tithis, ArgumentList argumentList);
Given a new instance tithis of this TemplateDeclaration, see if there already exists an instance.
TemplateInstance tithis template instance to check
ArgumentList argumentList For function templates, needed because different auto ref resolutions create different instances, even when template parameters are identical
that existing instance, or null when it doesn't exist
TemplateInstance addInstance(TemplateInstance ti);
Add instance ti to TemplateDeclaration's table of instances. Return a handle we can use to later remove it if it fails instantiation.
void removeInstance(TemplateInstance ti);
Remove TemplateInstance from table of instances.

Input handle returned by addInstance()

TemplateTupleParameter isVariadic();
Check if the last template parameter is a tuple one, and returns it if so, else returns null.
The last template parameter if it's a TemplateTupleParameter
const bool isOverloadable();
We can overload templates.
bool reliesOnTident(Type t, TemplateParameters* tparams, size_t iStart = 0);
Check whether the type t representation relies on one or more the template parameters.
Type t Tested type, if null, returns false.
TemplateParameters* tparams Template parameters.
size_t iStart Start index of tparams to limit the tested parameters. If it's nonzero, tparams[0..iStart] will be excluded from the test target.
bool reliesOnTemplateParameters(Type t, TemplateParameter[] tparams);
Check whether the type t representation relies on one or more the template parameters.
Type t Tested type, if null, returns false.
TemplateParameter[] tparams Template parameters.
abstract class TemplateParameter: dmd.ast_node.ASTNode;
class TemplateTypeParameter: dmd.dtemplate.TemplateParameter;

Syntax ident : specType = defaultType

class TemplateThisParameter: dmd.dtemplate.TemplateTypeParameter;

Syntax this ident : specType = defaultType

class TemplateValueParameter: dmd.dtemplate.TemplateParameter;

Syntax valType ident : specValue = defaultValue

class TemplateAliasParameter: dmd.dtemplate.TemplateParameter;

Syntax specType ident : specAlias = defaultAlias

class TemplateTupleParameter: dmd.dtemplate.TemplateParameter;

Syntax ident ...

class TemplateInstance: dmd.dsymbol.ScopeDsymbol;

Given foo!(args) => name = foo tiargs = args

Expressions* fargs;
For function template, these are the function names and arguments Relevant because different resolutions of auto ref parameters create different template instances even with the same template arguments
final const pure nothrow @nogc @property @safe bool semantictiargsdone();
has semanticTiargs() been done?
final const pure nothrow @nogc @property @safe bool havetempdecl();
if used second constructor
final const pure nothrow @nogc @property @safe bool gagged();
if the instantiation is done with error gagging
scope this(const ref Loc loc, TemplateDeclaration td, Objects* tiargs);
This constructor is only called when we figured out which function template to instantiate.
final void printInstantiationTrace(Classification cl = Classification.error, const(uint) max_shown = global.params.v.errorSupplementCount());
Given an error instantiating the TemplateInstance, give the nested TemplateInstance instantiations that got us here. Those are a list threaded into the nested scopes.
Classification cl classification of this trace as printing either errors or deprecations
const(uint) max_shown maximum number of trace elements printed (controlled with -v/-verror-limit)
final Identifier getIdent();
Lazily generate identifier for template instance. This is because 75% of the ident's are never needed.
final bool equalsx(TemplateInstance ti);
Compare proposed template instantiation with existing template instantiation. Note that this is not commutative because of the auto ref check.
TemplateInstance ti existing template instantiation
true for match
final bool isDiscardable();
true if the instances' innards are discardable.
The idea of this function is to see if the template instantiation can be 100% replaced with its eponymous member. All other members can be discarded, even in the compiler to free memory (for example, the template could be expanded in a region allocator, deemed trivial, the end result copied back out independently and the entire region freed), and can be elided entirely from the binary.
The current implementation affects code that generally looks like:
template foo(args...) {
    some_basic_type_or_string helper() { .... }
    enum foo = helper();
since it was the easiest starting point of implementation but it can and should be expanded more later.
final bool needsCodegen();
Returns true if this is not instantiated in non-root module, and is a part of non-speculative instantiatiation.

Note minst does not stabilize until semantic analysis is completed, so don't call this function during semantic analysis to return precise result.

final bool findTempDecl(Scope* sc, WithScopeSymbol* pwithsym);
Find template declaration corresponding to template instance.
false if finding fails.

Note This function is reentrant against error occurrence. If returns false, any members of this object won't be modified, and repetition call will reproduce same error.

final bool updateTempDecl(Scope* sc, Dsymbol s);
Confirm s is a valid template, then store it.

Input sc s candidate symbol of template. It may be: TemplateDeclaration FuncDeclaration with findTemplateDeclRoot() != NULL OverloadSet which contains candidates

true if updating succeeds.
static bool semanticTiargs(const ref Loc loc, Scope* sc, Objects* tiargs, int flags, TupleDeclaration atd = null);
Run semantic of tiargs as arguments of template.

Input loc sc tiargs array of template arguments flags 1: replace const variables with their initializers 2: don't devolve Parameter to Type atd tuple being optimized. If found, it's not expanded here but in AliasAssign semantic.

false if one or more arguments have errors.
final bool semanticTiargs(Scope* sc);
Run semantic on the elements of tiargs.

Input sc

false if one or more arguments have errors.

Note This function is reentrant against error occurrence. If returns false, all elements of tiargs won't be modified.

final bool findBestMatch(Scope* sc, ArgumentList argumentList);
Find the TemplateDeclaration that matches this TemplateInstance best.
Scope* sc the scope this TemplateInstance resides in
ArgumentList argumentList function arguments in case of a template function
true if a match was found, false otherwise
final bool needsTypeInference(Scope* sc, int flag = 0);
Determine if template instance is really a template function, and that template function needs to infer types from the function arguments.
Like findBestMatch, iterate possible template candidates, but just looks only the necessity of type inference.
final bool hasNestedArgs(Objects* args, bool isstatic);
Determines if a TemplateInstance will need a nested generation of the TemplateDeclaration. Sets enclosing property if so, and returns != 0;
final Dsymbols* appendToModuleMember();
Append 'this' to the specific module members[]
final void declareParameters(Scope* sc);
Declare parameters of template instance, initialize them with the template instance arguments.
final Identifier genIdent(Objects* args);
This instance needs an identifier for name mangling purposes. Create one by taking the template declaration name and adding the type signature for it.
void unSpeculative(Scope* sc, RootObject o);
IsExpression can evaluate the specified type speculatively, and even if it instantiates any symbols, they are normally unnecessary for the final executable. However, if those symbols leak to the actual code, compiler should remark them as non-speculative to generate their code and link to the final executable.
@safe bool definitelyValueParameter(Expression e);
Return true if e could be valid only as a template value parameter. Return false if it might be an alias or tuple. (Note that even in this case, it could still turn out to be a value).
class TemplateMixin: dmd.dtemplate.TemplateInstance;

Syntax mixin MixinTemplateName [TemplateArguments] Identifier;

struct TemplateInstanceBox;
This struct is needed for TemplateInstance to be the key in an associative array. Fixing would make it unnecessary.
MATCH matchArg(TemplateParameter tp, Loc instLoc, Scope* sc, Objects* tiargs, size_t i, TemplateParameters* parameters, ref Objects dedtypes, Declaration* psparam);
Match to a particular TemplateParameter.

Input instLoc location that the template is instantiated. tiargs[] actual arguments to template instance i i'th argument parameters[] template parameters dedtypes[] deduced arguments to template instance *psparam set to symbol declared and initialized to dedtypes[i]

struct TemplateStats;
Collect and print statistics on template instantiations.
static void incInstance(const TemplateDeclaration td, const TemplateInstance ti, bool listInstances);
Add this instance
TemplateDeclaration td template declaration
TemplateInstance ti instance of td
bool listInstances keep track of instances of templates
static void incUnique(const TemplateDeclaration td, const TemplateInstance ti);
Add this unique instance
void printTemplateStats(bool listInstances, ErrorSink eSink);
Print informational statistics on template instantiations.
bool listInstances list instances of templates
ErrorSink eSink where the print is sent
struct MATCHpair;
Pair of MATCHes
MATCH mta;
match template parameters by initial template arguments
MATCH mfa;
match template parameters by inferred template arguments