Template specialized functions creating runtime instructions?
ag0aep6g
anonymous at example.com
Wed Aug 21 00:18:46 UTC 2019
On 21.08.19 01:48, ads wrote:
> This piece of code creates a fizzbuzz string with template parameters.
>
> auto fizzbuzz(uint N)() {
> string accumulate;
> return fizzbuzz!N(accumulate);
> }
>
> auto fizzbuzz(uint N)(ref string result) if (N % 3 && N % 5) {
> import std.conv : to;
>
> result ~= N.to!string ~ "\n";
> return fizzbuzz!(N - 1)(result);
> }
[...]
> void main() {
> import std.stdio : writeln;
>
> fizzbuzz!50().writeln();
> }
>
>
> https://godbolt.org/z/hWENgc
>
> In the generated assembly, it looks like it is creating a lot of runtime
> instructions, contrary to my belief that templated codes are purely
> compile-time. I was expecting that the compiler would deduce the
> fizzbuzz string until 50 in compile-time and just print it in the
> run-time. Why is this not the case?
What you have there are function templates. You're generating functions
at compile time, and then you're calling those generated functions at
run time.
To do it all at compile time, you can skip the "functions" part and
generate the result directly:
template fizzbuzz(uint N) if (N % 3 && N % 5)
{
import std.conv : to;
enum fizzbuzz = N.to!string ~ "\n" ~ fizzbuzz!(N - 1);
}
/* ... etc ... */
You won't be able to use an accumulator, because mutation like that
doesn't mix with templates.
Alternatively, you can skip the "templates" part and call normal
functions at compile time (CTFE):
auto fizzbuzz(uint N)
{
string accumulate;
return fizzbuzz(N, accumulate);
}
auto fizzbuzz(uint N, ref string result)
{
import std.conv : to;
if (N % 3 && N % 5) result ~= N.to!string ~ "\n";
/* ... etc ... */
}
void main()
{
import std.stdio : writeln;
enum fz = fizzbuzz(50);
writeln(fz);
}
More information about the Digitalmars-d-learn
mailing list