From c79914db2da23767892c019c5c5602b06660ad64 Mon Sep 17 00:00:00 2001 From: Inkrementator <70717315+Inkrementator@users.noreply.github.com> Date: Wed, 19 Mar 2025 00:14:17 +0100 Subject: [PATCH] Fix #10440 Use right template constraint for `each` (#10689) The current contraints have been implemented in #3837 to make `each` behave more like `foreach` and automatically destructure tuples. I haven't publically documented this behavior because it is probably better these days to use `bind` for that. --- std/algorithm/iteration.d | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/std/algorithm/iteration.d b/std/algorithm/iteration.d index f8e1c05b6..32f584a1f 100644 --- a/std/algorithm/iteration.d +++ b/std/algorithm/iteration.d @@ -865,8 +865,8 @@ See_Also: $(REF tee, std,range) template each(alias fun = "a") { import std.meta : AliasSeq; - import std.traits : Parameters; - import std.typecons : Flag, Yes, No; + import std.traits : Parameters, isInstanceOf; + import std.typecons : Flag, Yes, No, Tuple; private: alias BinaryArgs = AliasSeq!(fun, "i", "a"); @@ -912,7 +912,8 @@ public: Flag!"each" each(Range)(Range r) if (!isForeachIterable!Range && ( isRangeIterable!Range || - __traits(compiles, typeof(r.front).length))) + // Tuples get automatically expanded if function takes right number of args + (isInputRange!Range && isInstanceOf!(Tuple, typeof(r.front))))) { static if (isRangeIterable!Range) { @@ -953,7 +954,11 @@ public: } else { - // range interface with >2 parameters. + /* Range over Tuples, fun must have correct number of args + * If number of args of fun is <= 2, calling fun(tuple) or fun(idx, tuple) + * will have precendence over fun(tuple.expand). + * Provide types to delegate params to control this. + */ for (auto range = r; !range.empty; range.popFront()) { static if (!is(typeof(fun(r.front.expand)) == Flag!"each"))