2. Zig and C++ require any code to be run at compile time to be specially marked (comptime, constexpr). D will run any code that appears in a const-expression at compile time.
3. Zig and C++ require that if a function is to be used for CTFE, the entire function must be compatible with CTFE. D only requires the path taken through the function to be compatible with CTFE. D even has a `__ctfe` pseudo-variable that can be used to branch within a function to compile-time and run-time paths.
fn double(n: usize) usize {
return 2*n;
}
const MyArrType = [double(5)]u8;
Similarly, point 3 is not really true either, what matters in Zig as well is the path that the function took during evaluation. const std = @import("std");
fn double(n: usize) usize {
if (n % 2 == 0) {
std.debug.print("even!", .{});
}
return 2*n;
}
const MyArrayType = [double(5)]u8; // this works
//const Bad = [double(6)]u8; // this will fail to compile
You are right about allocation not working during comptime evaluation at the moment, but this is not a final design decision, just the current status quo.The bigger issue D has with this example is that normal parameters are always runtime. If you wanted this to work in D you would need to implement 2 versions of "double", one that takes n as a template parameter and one that takes it as a runtime parameter. D keeps comptime and runtime parameters separate, making comptime-knowness a "parameter color" which in practice means having to implement things twice if you want it at comptime and often in different ways. There are some things that can work with both but it's small subset of both.
WRONG. if in a CTFE function works without problems. static if has nothing to do with CTFE. static if is conceptually a beefed up proper #ifdef/#endif.
The biggest issue D has is all the FUD and misconceptions that are propagated about it.
There are proposals to extend it, but there are some non-trivial const correctness issues to be solved there, AFAIK.