14namespace QXmpp::Private {
17concept HasShrinkToFit =
requires(
const T &t) {
22concept HasSqueeze =
requires(
const T &t) {
27concept HasPushBack =
requires(T t, T::value_type value) {
32concept HasInsert =
requires(T t, T::value_type value) {
36template<
typename OutputVector,
typename InputVector,
typename Converter>
37auto transform(
const InputVector &input, Converter convert)
40 HasPushBack<OutputVector> || HasInsert<OutputVector>,
41 "OutputVector must support push_back() or insert()");
44 if constexpr (std::ranges::sized_range<InputVector>) {
45 output.reserve(input.size());
47 for (
const auto &value : input) {
48 if constexpr (HasPushBack<OutputVector>) {
49 output.push_back(std::invoke(convert, value));
50 }
else if constexpr (HasInsert<OutputVector>) {
51 output.insert(std::invoke(convert, value));
57template<
typename OutputVector,
typename InputVector,
typename Converter>
58auto transform(InputVector &&input, Converter convert)
61 HasPushBack<OutputVector> || HasInsert<OutputVector>,
62 "OutputVector must support push_back() or insert()");
65 if constexpr (std::ranges::sized_range<InputVector>) {
66 output.reserve(input.size());
68 for (
auto it = input.begin(); it != input.end(); ++it) {
69 if constexpr (HasPushBack<OutputVector>) {
70 output.push_back(std::invoke(convert, std::move(*it)));
71 }
else if constexpr (HasInsert<OutputVector>) {
72 output.insert(std::invoke(convert, std::move(*it)));
78template<
typename OutputVector,
typename InputVector,
typename Converter>
79auto transformFilter(
const InputVector &input, Converter convert)
81 using OutputValue =
typename OutputVector::value_type;
83 if constexpr (std::ranges::sized_range<InputVector>) {
84 output.reserve(input.size());
86 for (
const auto &value : input) {
87 if (
const std::optional<OutputValue> result = std::invoke(convert, value)) {
88 output.push_back(*result);
91 if constexpr (std::ranges::sized_range<InputVector>) {
92 if constexpr (HasShrinkToFit<OutputVector>) {
93 output.shrink_to_fit();
94 }
else if constexpr (HasSqueeze<OutputVector>) {
102template<
typename Container,
typename... Args>
103auto contains(
const Container &container, Args &&...args) ->
bool
105 return std::ranges::find(container, std::forward<Args>(args)...) != std::end(container);
108template<
typename Container,
typename... Args>
109auto find(
const Container &container, Args &&...args) -> std::optional<typename Container::value_type>
111 auto it = std::ranges::find(container, std::forward<Args>(args)...);
112 if (it != std::end(container)) {
118template<
typename Container,
typename... Args>
119auto removeIf(Container &container, Args &&...args)
121 auto removedRange = std::ranges::remove_if(container, std::forward<Args>(args)...);
122 container.erase(removedRange.begin(), removedRange.end());
125template<
typename T,
typename Function>
126auto map(Function mapValue, std::optional<T> &&optValue) -> std::optional<std::invoke_result_t<Function, T &&>>
129 return mapValue(std::move(*optValue));
134template<
typename T,
typename Function>
135auto map(Function mapValue,
const std::optional<T> &optValue) -> std::optional<std::invoke_result_t<Function, T &&>>
138 return mapValue(*optValue);
143template<
typename Out,
typename Function,
typename... InTypes>
144auto map(Function mapValue, std::variant<InTypes...> &&variant)
147 [&](
auto &&v) -> Out {
148 if constexpr (std::is_invocable_v<Function,
decltype(v)>) {
149 return { mapValue(std::move(v)) };
157template<
typename Out,
typename Function,
typename... InTypes>
158auto map(Function mapValue,
const std::variant<InTypes...> &variant)
161 [&](
const auto &v) -> Out {
162 if constexpr (std::is_invocable_v<Function,
decltype(v)>) {
163 return { mapValue(v) };
171template<
typename To,
typename From>
172auto into(std::optional<From> &&value) -> std::optional<To>
175 return To { *value };
180template<
typename To,
typename From>
181auto into(
const std::optional<From> &value) -> std::optional<To>
184 return To { *value };
189template<
typename GreaterVariant,
typename... BaseTypes>
190auto into(std::variant<BaseTypes...> &&variant)
192 return std::visit([](
auto &&value) -> GreaterVariant {
return value; }, std::move(variant));
195template<
typename GreaterVariant,
typename... BaseTypes>
196auto into(
const std::variant<BaseTypes...> &variant)
198 return std::visit([](
const auto &value) -> GreaterVariant {
return value; }, variant);