From 2631a8b145985bec06f9b2bc44479bc54590c3a1 Mon Sep 17 00:00:00 2001 From: Elias Batek Date: Sun, 19 Jan 2025 07:08:37 +0100 Subject: [PATCH] Fix #10023 - Add `ctEval` to Phobos --- std/functional.d | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/std/functional.d b/std/functional.d index b1b138228..f9685e299 100644 --- a/std/functional.d +++ b/std/functional.d @@ -51,6 +51,9 @@ $(TR $(TH Function Name) $(TH Description) $(TR $(TD $(LREF bind)) $(TD Passes the fields of a struct as arguments to a function. )) + $(TR $(TD $(LREF ctEval)) + $(TD Enforces the execution of a function during compile-time. + )) )) Copyright: Copyright Andrei Alexandrescu 2008 - 2009. @@ -2167,3 +2170,50 @@ template bind(alias fun) static assert(!__traits(isRef, x)); }); } + +/** + * Enforces the execution of a function during compile-time. + * + * Computes the return value of a function call during compilation (CTFE). + * + * This is useful for call chains in functional programming + * where no explicit `enum` can be placed inline and would require splitting + * the pipeline. + * + * Params: + * fun = callable to evaluate + * See_also: + * $(LINK https://dlang.org/spec/function.html#interpretation) + */ +enum ctEval(alias fun) = fun; + +/// +@safe unittest +{ + import std.math : abs; + + // No explicit `enum` needed. + float result = ctEval!(abs(-3)); + assert(result == 3); + + // Can be statically asserted. + static assert(ctEval!(abs(-4)) == 4); + static assert(ctEval!(abs( 9)) == 9); +} + +/// +@safe unittest +{ + import core.stdc.math : round; + import std.conv : to; + import std.math : abs, PI, sin; + + // `round` from the C standard library cannot be interpreted at compile + // time, because it has no available source code. However the function + // calls preceding `round` can be evaluated during compile time. + int result = ctEval!(abs(sin(1.0)) * 180 / PI) + .round() + .to!int(); + + assert(result == 48); +}