From 836caf117379fe7371ad4bbad256a36d31ba5590 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Mon, 27 Oct 2025 11:57:07 +0100 Subject: [PATCH] libutil: add concepts for constraining iterables ("ranges") Change-Id: I5d75abb9d3713a3fab863666786aa8d38cc93dbd --- lix/libutil/concepts.hh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lix/libutil/concepts.hh b/lix/libutil/concepts.hh index 48bd1dbe1..831c045c9 100644 --- a/lix/libutil/concepts.hh +++ b/lix/libutil/concepts.hh @@ -1,6 +1,7 @@ #pragma once /// @file Defines C++ 20 concepts that std doesn't have. +#include #include namespace nix @@ -19,4 +20,25 @@ namespace nix template concept InvocableR = std::is_invocable_r_v; +/// @brief Like std::ranges::viewable_range<>, but also verifies the range's value type. +/// +/// Because C++ sucks ass, the check you want against the range's value type +/// might vary wildly. So this concept takes a *template template* argument, +/// which should be a type-trait like template-struct, which takes two template type +/// arguments, the first being std::ranges::range_value_t, and the other being +/// ElemT. +/// +/// @tparam RangeT The range type you want to constrain. +/// @tparam ItemT The item type you want RangeT's item type to be "like". +/// @tparam LikeT The to check if RangeT's item type is "like" ItemT. +template typename LikeT> +concept ViewOfLike = + std::ranges::viewable_range && LikeT, ItemT>::value; + +/// @brief Application of @ref ViewOfLike using @ref std::is_nothrow_convertible. +/// +/// @tparam RangeT The range type to constrain. +/// @tparam ItemT The item type you want RangeT's item type to be nothrow-convertible to. +template +concept ViewOf = ViewOfLike; }