From ec2daddf475a904713cfdd6f785d63a90fe0313d Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Sat, 14 Mar 2026 11:55:55 +0100 Subject: [PATCH] cmext/algorithm: add helpers functions cm::keys and cm::values --- Help/dev/source.rst | 8 ++++ Utilities/std/cmext/algorithm | 82 +++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/Help/dev/source.rst b/Help/dev/source.rst index 47336456f1..ec4e12c0e0 100644 --- a/Help/dev/source.rst +++ b/Help/dev/source.rst @@ -247,6 +247,14 @@ These are: * ``cm::contains``: Checks if element or key is contained in container. + * ``cm::keys`` + Extract keys from associative container or sequence container with tuple as + element + + * ``cm::values`` + Extract values from associative container or sequence container with tuple as + element + * ```` * ``cm::enum_set``: diff --git a/Utilities/std/cmext/algorithm b/Utilities/std/cmext/algorithm index cc85b0ae25..327a7721f1 100644 --- a/Utilities/std/cmext/algorithm +++ b/Utilities/std/cmext/algorithm @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -251,4 +252,85 @@ bool contains(Range const& range, Key const& key) } #endif +template < + typename Range, + cm::enable_if_t::value || + cm::is_unordered_associative_container::value, + int> = 0> +std::vector keys(Range const& range) +{ +#if defined(CMake_HAVE_CXX_RANGES) +# if __cplusplus >= 202302L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202302L) + return std::vector{ std::from_range, + std::views::keys(range) }; +# else + auto view = std::views::keys(range); + return std::vector{ view.begin(), view.end() }; +# endif +#else + return cm::views::keys(range); +#endif +} + +template < + typename Range, + cm::enable_if_t::value || + cm::is_unordered_associative_container::value, + int> = 0> +std::vector values(Range const& range) +{ +#if defined(CMake_HAVE_CXX_RANGES) +# if __cplusplus >= 202302L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202302L) + return std::vector{ std::from_range, + std::views::values(range) }; +# else + auto view = std::views::values(range); + return std::vector{ view.begin(), view.end() }; +# endif +#else + return cm::views::values(range); +#endif +} + +// sequence containers with std::pair<> or std::tuple<> as elements +template ::value && + cm::is_tuple<1, typename Range::value_type>::value, + int> = 0> +std::vector::type> +keys(Range const& range) +{ +#if defined(CMake_HAVE_CXX_RANGES) +# if __cplusplus >= 202302L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202302L) + return std::vector{ std::from_range, + std::views::keys(range) }; +# else + auto view = std::views::keys(range); + return std::vector{ view.begin(), view.end() }; +# endif +#else + return cm::views::keys(range); +#endif +} + +template ::value && + cm::is_tuple<2, typename Range::value_type>::value, + int> = 0> +std::vector::type> +keys(Range const& range) +{ +#if defined(CMake_HAVE_CXX_RANGES) +# if __cplusplus >= 202302L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202302L) + return std::vector{ std::from_range, + std::views::values(range) }; +# else + auto view = std::views::values(range); + return std::vector{ view.begin(), view.end() }; +# endif +#else + return cm::views::values(range); +#endif +} + } // namespace cm