Comment #0 by qs.il.paperinik — 2023-02-02T16:02:51Z
Add `__traits` to expose information about a template’s parameters: A template parameter has the following properties:
1. An identifier.
2. A kind: It is a value parameter, a type parameter, an alias parameter, or a sequence parameter. Arguably, a template `this` parameter is a type parameter, but IMO, it should be its own kind.
3. A type if it is a value parameter. (Alias and sequence parameters can be bound to value arguments that have types, but the parameter itself has no type.)
4. Optionally a constraint.
5. Optionally a default.
Chellanges:
1. Only values have types.
2. Types, constraints, and defaults might not be accessible, a symbolic (not a string) return is useful.
3. Types, constraints, and defaults can be dependent on previous paramters; a symbolic return is not possible in that case.
Proposed specification:
First, provide the trait `templateParameterLength` taking an alias to a template that returns the number of (lexical) template parameters. (By lexical, I mean that a sequence parameter counts as exactly 1 parameter, even if logically, it is “0 or many”.)
Note: For the following that take an index, if the index is out of range (≥ `templateParameterLength`), it is a compile error. The wording assumes that the index is in range.
For each template parameter property, provide a trait named `templateParameter(Identifier|Kind|Type|Constraint|Default)`, respectively, taking an alias to a template and an index that returns compile-time information of the respective properties (if available – a parameter might not have a type, constraint, or default).
E.g. `__traits(templateParameterKind, std.meta.AliasSeq, 0)` returns the kind of the only parameter: sequence.
Also provide the trait `templateParameterHas(Type|Constraint|Default)` taking an alias to a template and an index that returns a bool providing information about the availability of that property:
`templateParameterHasType` is a compile-error when the parameter is not of kind value. (The programmer should use `static if` to enusre the parameter queried is of kind value.) It returns `true` if the type is independent of previous template parameters and `false` if it is dependent on them. (This might be a best-effort, i.e. there could be edge cases in which `false` could be returned when `true` is actually possible.)
`templateParameterHas(Constraint|Default)` returns returns `true` if the template parameter has a constraint or default, respectively.
Identifiers are returned as strings (cf. `__traits(identifier)`). Unnamed parameters are syntactically not possible, the string is never empty or `null`.
The kind could be designated by a finite set of strings ("value", "type", "alias", "sequence", and "this") or by values of an `enum`.
`__traits(templateParameterType)` returns a sequence consisting of 1 or 2 entries: The first entry is the string used to define the parameter; the second entry is present and an alias to the type when `__traits(templateParameterHasType)` is `true` (and thus the type is well-defined).
For constraints and defaults, `__traits(templateParameter(Constraint|Default))` compiles if `__traits(templateParameterHas(Constraint|Default))` is `true`. Because constraints and defaults can depend on previous parameters, they cannot always be extracted symbolically. Again, a sequence consisting of 1 or 2 entries is returned: The first entry is the string consisting of the tokens making up the constraint/default, the second is present if the constraint/default is independent of previous parameters and thus can be extracted symbolically.
Comment #1 by robert.schadek — 2024-12-13T19:27:03Z