Challenge: write a template-instance free dispatcher for text printing
H. S. Teoh
hsteoh at qfbox.info
Thu May 28 23:43:26 UTC 2026
On Wed, May 27, 2026 at 06:50:08PM +0000, Paul Backus via Digitalmars-d wrote:
> On Wednesday, 27 May 2026 at 18:13:40 UTC, H. S. Teoh wrote:
> > Although D templates are extremely powerful and awesome for
> > metaprogramming, templates are ultimately not the right concept for
> > many CT tasks. What we *really* want is CTFE + type manipulation for
> > DbI to compute the final form of a template instantiation, then a
> > single template instantiation at the end to actualize it. The
> > current idiom of arbitrarily-complex templates nested arbitrarily
> > deep, while powerful, leads to needless template bloat.
>
> What you're describing is Lisp macros, and Walter has gone on record
> many, many times that D will never have them.
[...]
Not necessarily. Full-out macros leads to wild things like IOCCC-style
preprocessor macro abuse; what I'm talking about is in-language syntax
for making compile-time decisions in the code without causing hundreds
of template instantiations. We already somewhat have this in the form
of `static if` and `static foreach`. What's missing is things like
direct access to type operations, e.g., to construct `struct S2 {
const(T) val; }` given `struct S { T val; }` as a CT argument, without
using a truckload of templates to break S down into its components and
reassemble it with even more templates. CT variables for expressing
complex codegen tasks, like generating unique identifiers, etc..
All of this is currently already doable, but it involves convoluted
templates and string mixins, with the accompanying template bloat,
symbol size bloat, and weak compiler support (compiler cannot help you
with checking a mixin string until the string is fully assembled; until
then it's a free-for-all wild wild west of pasting code snippets
together and using hacks for things like generating unique identifiers
-- usually involving yet more templates).
Like I said, templates are powerful and can express all of this, but
they were never designed for AST manipulation of this sort, and as such,
are ill-suited for the task, no matter how capable. Symptoms of this we
already know: template bloat, symbol size bloat, compiler memory
exhaustion, etc.. We want the metaprogramming potential of templates,
but without the ugliness of recursive templates, template bloat, symbol
size bloat, and high memory usage.
The template instantiation really should happen only at the end, once
the CT logic has decided what the output code should be. The CT logic
itself shouldn't involve instantiating lots of temporary templates in
between, and definitely shouldn't involve recursive templates where it's
avoidable. A template function with static if / static foreach already
does this, but only to a limited extent. When you start having to do
more complex things like type manipulation, you quickly reach for
templates as the only current way of achieving what you need. The bulk
of std.traits, for example, generate truckloads of template symbols
every time you want to do the simplest of CT tasks. It doesn't have to
be this way. There should be a way to express most of std.traits
without instantiating templates.
T
--
Public parking: euphemism for paid parking. -- Flora
More information about the Digitalmars-d
mailing list