У меня долго была неправильная картина CTFE в D. Казалось, что если функция годится для вычисления при компиляции, компилятор сам вычислит её везде, где аргументы известны. На деле он делает это только там, где значение при компиляции обязательно нужно.
import std.stdio;
int sumSquares(int n)
{
if (!__ctfe)
writeln("sumSquares ran at run time");
int total = 0;
foreach (i; 0 .. n)
total += i * i;
return total;
}
enum a = sumSquares(4); // interpreted by the compiler
immutable b = sumSquares(4); // module scope, also compile time
void main()
{
auto c = sumSquares(4); // ordinary call, prints the line
writeln(a, " ", b, " ", c);
}
Программа один раз печатает строку про время выполнения, из c, а потом 14 14 14. И enum, и immutable на уровне модуля требуют значения во время компиляции, поэтому там sumSquares интерпретируется и __ctfe истинно. auto в main - обычный вызов, хотя ту же функцию с тем же аргументом только что дважды проинтерпретировали.
Теперь при какой-нибудь уборке кода замените этот auto на enum. В месте вызова меняется одно ключевое слово, а у функции тихо появилось новое требование - интерпретатор должен уметь выполнить её целиком. Неужели ключевое слово в объявлении - единственная подсказка для читателя?