mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
127 lines
3.5 KiB
C++
127 lines
3.5 KiB
C++
// -*-c++-*-
|
|
// vim: set ft=cpp:
|
|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#pragma once
|
|
|
|
#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
|
|
# define CMake_HAVE_CXX_RANGES
|
|
#endif
|
|
|
|
#if defined(CMake_HAVE_CXX_RANGES)
|
|
# include <ranges>
|
|
#else
|
|
# include <algorithm>
|
|
# include <iterator>
|
|
# include <tuple>
|
|
# include <vector>
|
|
|
|
# include <cm/type_traits>
|
|
# include <cmext/type_traits>
|
|
#endif
|
|
|
|
namespace cm {
|
|
namespace ranges {
|
|
namespace views {
|
|
#if defined(CMake_HAVE_CXX_RANGES)
|
|
|
|
using std::ranges::views::keys;
|
|
using std::ranges::views::values;
|
|
|
|
#else
|
|
|
|
// associative containers
|
|
template <
|
|
typename Range,
|
|
cm::enable_if_t<cm::is_associative_container<Range>::value ||
|
|
cm::is_unordered_associative_container<Range>::value,
|
|
int> = 0>
|
|
std::vector<typename Range::key_type> keys(Range const& range)
|
|
{
|
|
using key_type = typename Range::key_type;
|
|
|
|
std::vector<key_type> keys;
|
|
keys.reserve(range.size());
|
|
|
|
std::transform(range.begin(), range.end(),
|
|
std::back_inserter<std::vector<key_type>>(keys),
|
|
[](typename Range::value_type const& entry) -> key_type {
|
|
return entry.first;
|
|
});
|
|
|
|
return keys;
|
|
}
|
|
|
|
template <
|
|
typename Range,
|
|
cm::enable_if_t<cm::is_associative_container<Range>::value ||
|
|
cm::is_unordered_associative_container<Range>::value,
|
|
int> = 0>
|
|
std::vector<typename Range::mapped_type> values(Range const& range)
|
|
{
|
|
using value_type = typename Range::mapped_type;
|
|
|
|
std::vector<value_type> values;
|
|
values.reserve(range.size());
|
|
|
|
std::transform(range.begin(), range.end(),
|
|
std::back_inserter<std::vector<value_type>>(values),
|
|
[](typename Range::value_type const& entry) -> value_type {
|
|
return entry.second;
|
|
});
|
|
|
|
return values;
|
|
}
|
|
|
|
// sequence containers with std::pair<> or std::tuple<> as elements
|
|
template <typename Range,
|
|
cm::enable_if_t<cm::is_sequence_container<Range>::value &&
|
|
cm::is_tuple<1, typename Range::value_type>::value,
|
|
int> = 0>
|
|
std::vector<typename std::tuple_element<0, typename Range::value_type>::type>
|
|
keys(Range const& range)
|
|
{
|
|
using key_type =
|
|
typename std::tuple_element<0, typename Range::value_type>::type;
|
|
|
|
std::vector<key_type> keys;
|
|
keys.reserve(range.size());
|
|
|
|
std::transform(range.begin(), range.end(),
|
|
std::back_inserter<std::vector<key_type>>(keys),
|
|
[](typename Range::value_type const& entry) -> key_type {
|
|
return std::get<0>(entry);
|
|
});
|
|
|
|
return keys;
|
|
}
|
|
|
|
template <typename Range,
|
|
cm::enable_if_t<cm::is_sequence_container<Range>::value &&
|
|
cm::is_tuple<2, typename Range::value_type>::value,
|
|
int> = 0>
|
|
std::vector<typename std::tuple_element<1, typename Range::value_type>::type>
|
|
values(Range const& range)
|
|
{
|
|
using value_type =
|
|
typename std::tuple_element<1, typename Range::value_type>::type;
|
|
|
|
std::vector<value_type> values;
|
|
values.reserve(range.size());
|
|
|
|
std::transform(range.begin(), range.end(),
|
|
std::back_inserter<std::vector<value_type>>(values),
|
|
[](typename Range::value_type const& entry) -> value_type {
|
|
return std::get<1>(entry);
|
|
});
|
|
|
|
return values;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
}
|
|
namespace views = ranges::views;
|
|
}
|