mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Use ranges:: algorithms instead of base::
This commit is contained in:
parent
bc7c88c511
commit
ac99318f34
28 changed files with 751 additions and 596 deletions
|
@ -1873,11 +1873,15 @@ void ApiWrap::checkForUnreadMentions(const base::flat_set<MsgId> &possiblyReadMe
|
|||
}
|
||||
|
||||
void ApiWrap::cancelEditChatAdmins(not_null<ChatData*> chat) {
|
||||
_chatAdminsEnabledRequests.take(chat)
|
||||
| requestCanceller();
|
||||
_chatAdminsEnabledRequests.take(
|
||||
chat
|
||||
) | requestCanceller();
|
||||
|
||||
_chatAdminsSaveRequests.take(chat)
|
||||
| base::for_each_apply(requestCanceller());
|
||||
_chatAdminsSaveRequests.take(
|
||||
chat
|
||||
) | [&](auto &&requests) {
|
||||
ranges::for_each(std::move(requests), requestCanceller());
|
||||
};
|
||||
|
||||
_chatAdminsToSave.remove(chat);
|
||||
}
|
||||
|
@ -1975,8 +1979,8 @@ void ApiWrap::sendSaveChatAdminsRequests(not_null<ChatData*> chat) {
|
|||
}
|
||||
}
|
||||
}
|
||||
base::for_each(toRemove, removeOne);
|
||||
base::for_each(toAppoint, appointOne);
|
||||
ranges::for_each(toRemove, removeOne);
|
||||
ranges::for_each(toAppoint, appointOne);
|
||||
requestSendDelayed();
|
||||
}
|
||||
|
||||
|
|
|
@ -32,109 +32,4 @@ inline constexpr size_t array_size(const Type(&)[Size]) {
|
|||
return Size;
|
||||
}
|
||||
|
||||
template <typename Range, typename Method>
|
||||
decltype(auto) for_each(Range &&range, Method &&method) {
|
||||
return std::for_each(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Method>(method));
|
||||
}
|
||||
|
||||
template <typename Method>
|
||||
decltype(auto) for_each_apply(Method &&method) {
|
||||
return [&method](auto &&range) {
|
||||
return for_each(std::forward<decltype(range)>(range), std::forward<Method>(method));
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Range, typename Value>
|
||||
decltype(auto) find(Range &&range, Value &&value) {
|
||||
return std::find(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Value>(value));
|
||||
}
|
||||
|
||||
template <typename Range, typename Predicate>
|
||||
decltype(auto) find_if(Range &&range, Predicate &&predicate) {
|
||||
return std::find_if(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Predicate>(predicate));
|
||||
}
|
||||
|
||||
template <typename Range, typename Type>
|
||||
decltype(auto) lower_bound(Range &&range, Type &&value) {
|
||||
return std::lower_bound(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Type>(value));
|
||||
}
|
||||
|
||||
template <typename Range, typename Type, typename Predicate>
|
||||
decltype(auto) lower_bound(Range &&range, Type &&value, Predicate &&predicate) {
|
||||
return std::lower_bound(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Type>(value),
|
||||
std::forward<Predicate>(predicate));
|
||||
}
|
||||
|
||||
template <typename Range, typename Type>
|
||||
decltype(auto) upper_bound(Range &&range, Type &&value) {
|
||||
return std::upper_bound(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Type>(value));
|
||||
}
|
||||
|
||||
template <typename Range, typename Type, typename Predicate>
|
||||
decltype(auto) upper_bound(Range &&range, Type &&value, Predicate &&predicate) {
|
||||
return std::upper_bound(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Type>(value),
|
||||
std::forward<Predicate>(predicate));
|
||||
}
|
||||
|
||||
template <typename Range, typename Type>
|
||||
decltype(auto) equal_range(Range &&range, Type &&value) {
|
||||
return std::equal_range(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Type>(value));
|
||||
}
|
||||
|
||||
template <typename Range, typename Type, typename Predicate>
|
||||
decltype(auto) equal_range(Range &&range, Type &&value, Predicate &&predicate) {
|
||||
return std::equal_range(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Type>(value),
|
||||
std::forward<Predicate>(predicate));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
decltype(auto) sort(Range &&range) {
|
||||
return std::sort(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)));
|
||||
}
|
||||
|
||||
template <typename Range, typename Predicate>
|
||||
decltype(auto) sort(Range &&range, Predicate &&predicate) {
|
||||
return std::sort(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Predicate>(predicate));
|
||||
}
|
||||
|
||||
template <typename Range, typename Predicate>
|
||||
decltype(auto) stable_partition(Range &&range, Predicate &&predicate) {
|
||||
return std::stable_partition(
|
||||
std::begin(std::forward<Range>(range)),
|
||||
std::end(std::forward<Range>(range)),
|
||||
std::forward<Predicate>(predicate));
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
|
|
@ -21,8 +21,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include "base/optional.h"
|
||||
#include "base/algorithm.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
|
@ -39,18 +39,41 @@ template <
|
|||
class flat_multi_map;
|
||||
|
||||
template <
|
||||
typename Me,
|
||||
typename Key,
|
||||
typename Type,
|
||||
typename Compare,
|
||||
typename iterator_impl,
|
||||
typename pointer_impl,
|
||||
typename reference_impl>
|
||||
class flat_multi_map_iterator_base_impl;
|
||||
|
||||
template <typename Key>
|
||||
class flat_multi_map_key_const_wrap {
|
||||
public:
|
||||
constexpr flat_multi_map_key_const_wrap(const Key &value)
|
||||
: _value(value) {
|
||||
}
|
||||
constexpr flat_multi_map_key_const_wrap(Key &&value)
|
||||
: _value(std::move(value)) {
|
||||
}
|
||||
inline constexpr operator const Key&() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
Key _value;
|
||||
|
||||
};
|
||||
|
||||
template <typename Key, typename Type>
|
||||
using flat_multi_map_pair_type = std::pair<
|
||||
flat_multi_map_key_const_wrap<Key>,
|
||||
Type>;
|
||||
|
||||
template <
|
||||
typename Me,
|
||||
typename Key,
|
||||
typename Type,
|
||||
typename Compare,
|
||||
typename iterator_impl,
|
||||
typename pointer_impl,
|
||||
typename reference_impl>
|
||||
|
@ -58,12 +81,13 @@ class flat_multi_map_iterator_base_impl {
|
|||
public:
|
||||
using iterator_category = typename iterator_impl::iterator_category;
|
||||
|
||||
using value_type = typename flat_multi_map<Key, Type, Compare>::value_type;
|
||||
using pair_type = flat_multi_map_pair_type<Key, Type>;
|
||||
using value_type = pair_type;
|
||||
using difference_type = typename iterator_impl::difference_type;
|
||||
using pointer = pointer_impl;
|
||||
using const_pointer = typename flat_multi_map<Key, Type, Compare>::const_pointer;
|
||||
using const_pointer = const pair_type*;
|
||||
using reference = reference_impl;
|
||||
using const_reference = typename flat_multi_map<Key, Type, Compare>::const_reference;
|
||||
using const_reference = const pair_type&;
|
||||
|
||||
flat_multi_map_iterator_base_impl(iterator_impl impl = iterator_impl())
|
||||
: _impl(impl) {
|
||||
|
@ -81,43 +105,44 @@ public:
|
|||
const_pointer operator->() const {
|
||||
return std::addressof(**this);
|
||||
}
|
||||
flat_multi_map_iterator_base_impl &operator++() {
|
||||
Me &operator++() {
|
||||
++_impl;
|
||||
return *this;
|
||||
return static_cast<Me&>(*this);
|
||||
}
|
||||
flat_multi_map_iterator_base_impl operator++(int) {
|
||||
Me operator++(int) {
|
||||
return _impl++;
|
||||
}
|
||||
flat_multi_map_iterator_base_impl &operator--() {
|
||||
Me &operator--() {
|
||||
--_impl;
|
||||
return *this;
|
||||
return static_cast<Me&>(*this);
|
||||
}
|
||||
flat_multi_map_iterator_base_impl operator--(int) {
|
||||
Me operator--(int) {
|
||||
return _impl--;
|
||||
}
|
||||
flat_multi_map_iterator_base_impl &operator+=(difference_type offset) {
|
||||
Me &operator+=(difference_type offset) {
|
||||
_impl += offset;
|
||||
return *this;
|
||||
return static_cast<Me&>(*this);
|
||||
}
|
||||
flat_multi_map_iterator_base_impl operator+(difference_type offset) const {
|
||||
Me operator+(difference_type offset) const {
|
||||
return _impl + offset;
|
||||
}
|
||||
flat_multi_map_iterator_base_impl &operator-=(difference_type offset) {
|
||||
Me &operator-=(difference_type offset) {
|
||||
_impl -= offset;
|
||||
return *this;
|
||||
return static_cast<Me&>(*this);
|
||||
}
|
||||
flat_multi_map_iterator_base_impl operator-(difference_type offset) const {
|
||||
Me operator-(difference_type offset) const {
|
||||
return _impl - offset;
|
||||
}
|
||||
template <
|
||||
typename other_me,
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
difference_type operator-(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
other_me,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
|
@ -131,42 +156,45 @@ public:
|
|||
}
|
||||
|
||||
template <
|
||||
typename other_me,
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
bool operator==(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
other_me,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
return _impl == right._impl;
|
||||
}
|
||||
template <
|
||||
typename other_me,
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
bool operator!=(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
other_me,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
return _impl != right._impl;
|
||||
}
|
||||
template <
|
||||
typename other_me,
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
bool operator<(
|
||||
const flat_multi_map_iterator_base_impl<
|
||||
other_me,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl,
|
||||
other_pointer_impl,
|
||||
other_reference_impl> &right) const {
|
||||
|
@ -175,12 +203,17 @@ public:
|
|||
|
||||
private:
|
||||
iterator_impl _impl;
|
||||
friend class flat_multi_map<Key, Type, Compare>;
|
||||
|
||||
template <
|
||||
typename OtherKey,
|
||||
typename OtherType,
|
||||
typename OtherCompare,
|
||||
typename OtherCompare>
|
||||
friend class flat_multi_map;
|
||||
|
||||
template <
|
||||
typename OtherMe,
|
||||
typename OtherKey,
|
||||
typename OtherType,
|
||||
typename other_iterator_impl,
|
||||
typename other_pointer_impl,
|
||||
typename other_reference_impl>
|
||||
|
@ -190,131 +223,50 @@ private:
|
|||
|
||||
template <typename Key, typename Type, typename Compare>
|
||||
class flat_multi_map {
|
||||
class key_const_wrap {
|
||||
public:
|
||||
constexpr key_const_wrap(const Key &value) : _value(value) {
|
||||
}
|
||||
constexpr key_const_wrap(Key &&value) : _value(std::move(value)) {
|
||||
}
|
||||
inline constexpr operator const Key&() const {
|
||||
return _value;
|
||||
}
|
||||
public:
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
class reverse_iterator;
|
||||
class const_reverse_iterator;
|
||||
|
||||
private:
|
||||
Key _value;
|
||||
|
||||
};
|
||||
using pair_type = std::pair<key_const_wrap, Type>;
|
||||
|
||||
class compare {
|
||||
public:
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType1>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType1>, pair_type> &&
|
||||
!std::is_same_v<std::decay_t<OtherType2>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType2>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &b) const {
|
||||
return Compare()(
|
||||
std::forward<OtherType1>(a),
|
||||
std::forward<OtherType2>(b));
|
||||
}
|
||||
inline constexpr auto operator()(
|
||||
const key_const_wrap &a,
|
||||
const key_const_wrap &b) const {
|
||||
return operator()(
|
||||
static_cast<const Key&>(a),
|
||||
static_cast<const Key&>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
const key_const_wrap &a,
|
||||
OtherType &&b) const {
|
||||
return operator()(
|
||||
static_cast<const Key&>(a),
|
||||
std::forward<OtherType>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType &&a,
|
||||
const key_const_wrap &b) const {
|
||||
return operator()(
|
||||
std::forward<OtherType>(a),
|
||||
static_cast<const Key&>(b));
|
||||
}
|
||||
inline constexpr auto operator()(
|
||||
const pair_type &a,
|
||||
const pair_type &b) const {
|
||||
return operator()(a.first, b.first);
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
const pair_type &a,
|
||||
OtherType &&b) const {
|
||||
return operator()(a.first, std::forward<OtherType>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType &&a,
|
||||
const pair_type &b) const {
|
||||
return operator()(std::forward<OtherType>(a), b.first);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using impl = std::deque<pair_type>;
|
||||
private:
|
||||
using key_const_wrap = flat_multi_map_key_const_wrap<Key>;
|
||||
using pair_type = flat_multi_map_pair_type<Key, Type>;
|
||||
using impl_t = std::deque<pair_type>;
|
||||
|
||||
using iterator_base = flat_multi_map_iterator_base_impl<
|
||||
iterator,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::iterator,
|
||||
typename impl_t::iterator,
|
||||
pair_type*,
|
||||
pair_type&>;
|
||||
using const_iterator_base = flat_multi_map_iterator_base_impl<
|
||||
const_iterator,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::const_iterator,
|
||||
typename impl_t::const_iterator,
|
||||
const pair_type*,
|
||||
const pair_type&>;
|
||||
using reverse_iterator_base = flat_multi_map_iterator_base_impl<
|
||||
reverse_iterator,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::reverse_iterator,
|
||||
typename impl_t::reverse_iterator,
|
||||
pair_type*,
|
||||
pair_type&>;
|
||||
using const_reverse_iterator_base = flat_multi_map_iterator_base_impl<
|
||||
const_reverse_iterator,
|
||||
Key,
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::const_reverse_iterator,
|
||||
typename impl_t::const_reverse_iterator,
|
||||
const pair_type*,
|
||||
const pair_type&>;
|
||||
|
||||
public:
|
||||
using value_type = pair_type;
|
||||
using size_type = typename impl::size_type;
|
||||
using difference_type = typename impl::difference_type;
|
||||
using size_type = typename impl_t::size_type;
|
||||
using difference_type = typename impl_t::difference_type;
|
||||
using pointer = pair_type*;
|
||||
using const_pointer = const pair_type*;
|
||||
using reference = pair_type&;
|
||||
|
@ -324,6 +276,7 @@ public:
|
|||
class iterator : public iterator_base {
|
||||
public:
|
||||
using iterator_base::iterator_base;
|
||||
iterator() = default;
|
||||
iterator(const iterator_base &other) : iterator_base(other) {
|
||||
}
|
||||
friend class const_iterator;
|
||||
|
@ -332,6 +285,7 @@ public:
|
|||
class const_iterator : public const_iterator_base {
|
||||
public:
|
||||
using const_iterator_base::const_iterator_base;
|
||||
const_iterator() = default;
|
||||
const_iterator(const_iterator_base other) : const_iterator_base(other) {
|
||||
}
|
||||
const_iterator(const iterator &other) : const_iterator_base(other._impl) {
|
||||
|
@ -342,6 +296,7 @@ public:
|
|||
class reverse_iterator : public reverse_iterator_base {
|
||||
public:
|
||||
using reverse_iterator_base::reverse_iterator_base;
|
||||
reverse_iterator() = default;
|
||||
reverse_iterator(reverse_iterator_base other) : reverse_iterator_base(other) {
|
||||
}
|
||||
friend class const_reverse_iterator;
|
||||
|
@ -350,6 +305,7 @@ public:
|
|||
class const_reverse_iterator : public const_reverse_iterator_base {
|
||||
public:
|
||||
using const_reverse_iterator_base::const_reverse_iterator_base;
|
||||
const_reverse_iterator() = default;
|
||||
const_reverse_iterator(const_reverse_iterator_base other) : const_reverse_iterator_base(other) {
|
||||
}
|
||||
const_reverse_iterator(const reverse_iterator &other) : const_reverse_iterator_base(other._impl) {
|
||||
|
@ -358,50 +314,50 @@ public:
|
|||
};
|
||||
|
||||
size_type size() const {
|
||||
return _impl.size();
|
||||
return impl().size();
|
||||
}
|
||||
bool empty() const {
|
||||
return _impl.empty();
|
||||
return impl().empty();
|
||||
}
|
||||
void clear() {
|
||||
_impl.clear();
|
||||
impl().clear();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return _impl.begin();
|
||||
return impl().begin();
|
||||
}
|
||||
iterator end() {
|
||||
return _impl.end();
|
||||
return impl().end();
|
||||
}
|
||||
const_iterator begin() const {
|
||||
return _impl.begin();
|
||||
return impl().begin();
|
||||
}
|
||||
const_iterator end() const {
|
||||
return _impl.end();
|
||||
return impl().end();
|
||||
}
|
||||
const_iterator cbegin() const {
|
||||
return _impl.cbegin();
|
||||
return impl().cbegin();
|
||||
}
|
||||
const_iterator cend() const {
|
||||
return _impl.cend();
|
||||
return impl().cend();
|
||||
}
|
||||
reverse_iterator rbegin() {
|
||||
return _impl.rbegin();
|
||||
return impl().rbegin();
|
||||
}
|
||||
reverse_iterator rend() {
|
||||
return _impl.rend();
|
||||
return impl().rend();
|
||||
}
|
||||
const_reverse_iterator rbegin() const {
|
||||
return _impl.rbegin();
|
||||
return impl().rbegin();
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return _impl.rend();
|
||||
return impl().rend();
|
||||
}
|
||||
const_reverse_iterator crbegin() const {
|
||||
return _impl.crbegin();
|
||||
return impl().crbegin();
|
||||
}
|
||||
const_reverse_iterator crend() const {
|
||||
return _impl.crend();
|
||||
return impl().crend();
|
||||
}
|
||||
|
||||
reference front() {
|
||||
|
@ -419,25 +375,25 @@ public:
|
|||
|
||||
iterator insert(const value_type &value) {
|
||||
if (empty() || compare()(value.first, front().first)) {
|
||||
_impl.push_front(value);
|
||||
impl().push_front(value);
|
||||
return begin();
|
||||
} else if (!compare()(value.first, back().first)) {
|
||||
_impl.push_back(value);
|
||||
impl().push_back(value);
|
||||
return (end() - 1);
|
||||
}
|
||||
auto where = getUpperBound(value.first);
|
||||
return _impl.insert(where, value);
|
||||
return impl().insert(where, value);
|
||||
}
|
||||
iterator insert(value_type &&value) {
|
||||
if (empty() || compare()(value.first, front().first)) {
|
||||
_impl.push_front(std::move(value));
|
||||
impl().push_front(std::move(value));
|
||||
return begin();
|
||||
} else if (!compare()(value.first, back().first)) {
|
||||
_impl.push_back(std::move(value));
|
||||
impl().push_back(std::move(value));
|
||||
return (end() - 1);
|
||||
}
|
||||
auto where = getUpperBound(value.first);
|
||||
return _impl.insert(where, std::move(value));
|
||||
return impl().insert(where, std::move(value));
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
|
@ -454,7 +410,7 @@ public:
|
|||
if (compare()(key, where->first)) {
|
||||
return false;
|
||||
}
|
||||
_impl.erase(where);
|
||||
impl().erase(where);
|
||||
return true;
|
||||
}
|
||||
int removeAll(const Key &key) {
|
||||
|
@ -467,15 +423,15 @@ public:
|
|||
if (range.first == range.second) {
|
||||
return 0;
|
||||
}
|
||||
_impl.erase(range.first, range.second);
|
||||
impl().erase(range.first, range.second);
|
||||
return (range.second - range.first);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator where) {
|
||||
return _impl.erase(where._impl);
|
||||
return impl().erase(where._impl);
|
||||
}
|
||||
iterator erase(const_iterator from, const_iterator till) {
|
||||
return _impl.erase(from._impl, till._impl);
|
||||
return impl().erase(from._impl, till._impl);
|
||||
}
|
||||
|
||||
iterator findFirst(const Key &key) {
|
||||
|
@ -485,7 +441,7 @@ public:
|
|||
return end();
|
||||
}
|
||||
auto where = getLowerBound(key);
|
||||
return compare()(key, where->first) ? _impl.end() : where;
|
||||
return compare()(key, where->first) ? impl().end() : where;
|
||||
}
|
||||
|
||||
const_iterator findFirst(const Key &key) const {
|
||||
|
@ -495,7 +451,7 @@ public:
|
|||
return end();
|
||||
}
|
||||
auto where = getLowerBound(key);
|
||||
return compare()(key, where->first) ? _impl.end() : where;
|
||||
return compare()(key, where->first) ? impl().end() : where;
|
||||
}
|
||||
|
||||
bool contains(const Key &key) const {
|
||||
|
@ -512,32 +468,167 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
impl _impl;
|
||||
friend class flat_map<Key, Type, Compare>;
|
||||
|
||||
typename impl::iterator getLowerBound(const Key &key) {
|
||||
return base::lower_bound(_impl, key, compare());
|
||||
struct transparent_compare : Compare {
|
||||
inline constexpr const Compare &initial() const noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType1>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType1>, pair_type> &&
|
||||
!std::is_same_v<std::decay_t<OtherType2>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType2>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &&b) const {
|
||||
return initial()(
|
||||
std::forward<OtherType1>(a),
|
||||
std::forward<OtherType2>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &&b) const -> std::enable_if_t<
|
||||
std::is_same_v<std::decay_t<OtherType1>, key_const_wrap> &&
|
||||
std::is_same_v<std::decay_t<OtherType2>, key_const_wrap>, bool> {
|
||||
return initial()(
|
||||
static_cast<const Key&>(a),
|
||||
static_cast<const Key&>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
const key_const_wrap &a,
|
||||
OtherType &&b) const {
|
||||
return initial()(
|
||||
static_cast<const Key&>(a),
|
||||
std::forward<OtherType>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, key_const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType &&a,
|
||||
const key_const_wrap &b) const {
|
||||
return initial()(
|
||||
std::forward<OtherType>(a),
|
||||
static_cast<const Key&>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &&b) const -> std::enable_if_t<
|
||||
std::is_same_v<std::decay_t<OtherType1>, pair_type> &&
|
||||
std::is_same_v<std::decay_t<OtherType2>, pair_type>, bool> {
|
||||
return initial()(
|
||||
static_cast<const Key&>(a.first),
|
||||
static_cast<const Key&>(b.first));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
const pair_type &a,
|
||||
OtherType &&b) const {
|
||||
return operator()(
|
||||
static_cast<const Key&>(a.first),
|
||||
std::forward<OtherType>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, pair_type>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType &&a,
|
||||
const pair_type &b) const {
|
||||
return operator()(
|
||||
std::forward<OtherType>(a),
|
||||
static_cast<const Key&>(b.first));
|
||||
}
|
||||
|
||||
};
|
||||
struct Data : transparent_compare {
|
||||
template <typename ...Args>
|
||||
Data(Args &&...args)
|
||||
: elements(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
impl_t elements;
|
||||
};
|
||||
|
||||
Data _data;
|
||||
const transparent_compare &compare() const noexcept {
|
||||
return _data;
|
||||
}
|
||||
typename impl::const_iterator getLowerBound(const Key &key) const {
|
||||
return base::lower_bound(_impl, key, compare());
|
||||
const impl_t &impl() const noexcept {
|
||||
return _data.elements;
|
||||
}
|
||||
typename impl::iterator getUpperBound(const Key &key) {
|
||||
return base::upper_bound(_impl, key, compare());
|
||||
impl_t &impl() noexcept {
|
||||
return _data.elements;
|
||||
}
|
||||
typename impl::const_iterator getUpperBound(const Key &key) const {
|
||||
return base::upper_bound(_impl, key, compare());
|
||||
|
||||
typename impl_t::iterator getLowerBound(const Key &key) {
|
||||
return std::lower_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
key,
|
||||
compare());
|
||||
}
|
||||
typename impl_t::const_iterator getLowerBound(const Key &key) const {
|
||||
return std::lower_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
key,
|
||||
compare());
|
||||
}
|
||||
typename impl_t::iterator getUpperBound(const Key &key) {
|
||||
return std::upper_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
key,
|
||||
compare());
|
||||
}
|
||||
typename impl_t::const_iterator getUpperBound(const Key &key) const {
|
||||
return std::upper_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
key,
|
||||
compare());
|
||||
}
|
||||
std::pair<
|
||||
typename impl::iterator,
|
||||
typename impl::iterator
|
||||
typename impl_t::iterator,
|
||||
typename impl_t::iterator
|
||||
> getEqualRange(const Key &key) {
|
||||
return base::equal_range(_impl, key, compare());
|
||||
return std::equal_range(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
key,
|
||||
compare());
|
||||
}
|
||||
std::pair<
|
||||
typename impl::const_iterator,
|
||||
typename impl::const_iterator
|
||||
typename impl_t::const_iterator,
|
||||
typename impl_t::const_iterator
|
||||
> getEqualRange(const Key &key) const {
|
||||
return base::equal_range(_impl, key, compare());
|
||||
return std::equal_range(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
key,
|
||||
compare());
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -545,7 +636,6 @@ private:
|
|||
template <typename Key, typename Type, typename Compare>
|
||||
class flat_map : private flat_multi_map<Key, Type, Compare> {
|
||||
using parent = flat_multi_map<Key, Type, Compare>;
|
||||
using compare = typename parent::compare;
|
||||
using pair_type = typename parent::pair_type;
|
||||
|
||||
public:
|
||||
|
@ -579,30 +669,30 @@ public:
|
|||
using parent::contains;
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type &value) {
|
||||
if (this->empty() || compare()(value.first, this->front().first)) {
|
||||
this->_impl.push_front(value);
|
||||
if (this->empty() || this->compare()(value.first, this->front().first)) {
|
||||
this->impl().push_front(value);
|
||||
return { this->begin(), true };
|
||||
} else if (compare()(this->back().first, value.first)) {
|
||||
this->_impl.push_back(value);
|
||||
} else if (this->compare()(this->back().first, value.first)) {
|
||||
this->impl().push_back(value);
|
||||
return { this->end() - 1, true };
|
||||
}
|
||||
auto where = this->getLowerBound(value.first);
|
||||
if (compare()(value.first, where->first)) {
|
||||
return { this->_impl.insert(where, value), true };
|
||||
if (this->compare()(value.first, where->first)) {
|
||||
return { this->impl().insert(where, value), true };
|
||||
}
|
||||
return { where, false };
|
||||
}
|
||||
std::pair<iterator, bool> insert(value_type &&value) {
|
||||
if (this->empty() || compare()(value.first, this->front().first)) {
|
||||
this->_impl.push_front(std::move(value));
|
||||
if (this->empty() || this->compare()(value.first, this->front().first)) {
|
||||
this->impl().push_front(std::move(value));
|
||||
return { this->begin(), true };
|
||||
} else if (compare()(this->back().first, value.first)) {
|
||||
this->_impl.push_back(std::move(value));
|
||||
} else if (this->compare()(this->back().first, value.first)) {
|
||||
this->impl().push_back(std::move(value));
|
||||
return { this->end() - 1, true };
|
||||
}
|
||||
auto where = this->getLowerBound(value.first);
|
||||
if (compare()(value.first, where->first)) {
|
||||
return { this->_impl.insert(where, std::move(value)), true };
|
||||
if (this->compare()(value.first, where->first)) {
|
||||
return { this->impl().insert(where, std::move(value)), true };
|
||||
}
|
||||
return { where, false };
|
||||
}
|
||||
|
@ -618,21 +708,21 @@ public:
|
|||
std::pair<iterator, bool> try_emplace(
|
||||
const Key &key,
|
||||
Args&&... args) {
|
||||
if (this->empty() || compare()(key, this->front().first)) {
|
||||
this->_impl.push_front(value_type(
|
||||
if (this->empty() || this->compare()(key, this->front().first)) {
|
||||
this->impl().push_front(value_type(
|
||||
key,
|
||||
Type(std::forward<Args>(args)...)));
|
||||
return { this->begin(), true };
|
||||
} else if (compare()(this->back().first, key)) {
|
||||
this->_impl.push_back(value_type(
|
||||
} else if (this->compare()(this->back().first, key)) {
|
||||
this->impl().push_back(value_type(
|
||||
key,
|
||||
Type(std::forward<Args>(args)...)));
|
||||
return { this->end() - 1, true };
|
||||
}
|
||||
auto where = this->getLowerBound(key);
|
||||
if (compare()(key, where->first)) {
|
||||
if (this->compare()(key, where->first)) {
|
||||
return {
|
||||
this->_impl.insert(
|
||||
this->impl().insert(
|
||||
where,
|
||||
value_type(
|
||||
key,
|
||||
|
@ -655,16 +745,16 @@ public:
|
|||
}
|
||||
|
||||
Type &operator[](const Key &key) {
|
||||
if (this->empty() || compare()(key, this->front().first)) {
|
||||
this->_impl.push_front({ key, Type() });
|
||||
if (this->empty() || this->compare()(key, this->front().first)) {
|
||||
this->impl().push_front({ key, Type() });
|
||||
return this->front().second;
|
||||
} else if (compare()(this->back().first, key)) {
|
||||
this->_impl.push_back({ key, Type() });
|
||||
} else if (this->compare()(this->back().first, key)) {
|
||||
this->impl().push_back({ key, Type() });
|
||||
return this->back().second;
|
||||
}
|
||||
auto where = this->getLowerBound(key);
|
||||
if (compare()(key, where->first)) {
|
||||
return this->_impl.insert(where, { key, Type() })->second;
|
||||
if (this->compare()(key, where->first)) {
|
||||
return this->impl().insert(where, { key, Type() })->second;
|
||||
}
|
||||
return where->second;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "base/flat_map.h"
|
||||
#include <string>
|
||||
|
||||
struct int_wrap {
|
||||
int value;
|
||||
};
|
||||
struct int_wrap_comparator {
|
||||
inline bool operator()(const int_wrap &a, const int_wrap &b) const {
|
||||
return a.value < b.value;
|
||||
}
|
||||
};
|
||||
|
||||
using namespace std;
|
||||
|
||||
TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") {
|
||||
|
@ -49,3 +58,28 @@ TEST_CASE("flat_maps should keep items sorted by key", "[flat_map]") {
|
|||
checkSorted();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("flat_maps custom comparator", "[flat_map]") {
|
||||
base::flat_map<int_wrap, string, int_wrap_comparator> v;
|
||||
v.emplace({ 0 }, "a");
|
||||
v.emplace({ 5 }, "b");
|
||||
v.emplace({ 4 }, "d");
|
||||
v.emplace({ 2 }, "e");
|
||||
|
||||
auto checkSorted = [&] {
|
||||
auto prev = v.begin();
|
||||
REQUIRE(prev != v.end());
|
||||
for (auto i = prev + 1; i != v.end(); prev = i, ++i) {
|
||||
REQUIRE(int_wrap_comparator()(prev->first, i->first));
|
||||
}
|
||||
};
|
||||
REQUIRE(v.size() == 4);
|
||||
checkSorted();
|
||||
|
||||
SECTION("adding item puts it in the right position") {
|
||||
v.emplace({ 3 }, "c");
|
||||
REQUIRE(v.size() == 5);
|
||||
REQUIRE(v.find({ 3 }) != v.end());
|
||||
checkSorted();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include "base/algorithm.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace base {
|
||||
|
||||
|
@ -31,28 +31,29 @@ class flat_set;
|
|||
template <typename Type, typename Compare = std::less<>>
|
||||
class flat_multi_set;
|
||||
|
||||
template <typename Type, typename Compare, typename iterator_impl>
|
||||
template <typename Type, typename iterator_impl>
|
||||
class flat_multi_set_iterator_impl;
|
||||
|
||||
template <typename Type, typename Compare, typename iterator_impl>
|
||||
template <typename Type, typename iterator_impl>
|
||||
class flat_multi_set_iterator_impl {
|
||||
public:
|
||||
using iterator_category = typename iterator_impl::iterator_category;
|
||||
|
||||
using value_type = typename flat_multi_set<Type, Compare>::value_type;
|
||||
using value_type = Type;
|
||||
using difference_type = typename iterator_impl::difference_type;
|
||||
using pointer = typename flat_multi_set<Type, Compare>::pointer;
|
||||
using reference = typename flat_multi_set<Type, Compare>::reference;
|
||||
using pointer = const Type*;
|
||||
using reference = const Type&;
|
||||
|
||||
flat_multi_set_iterator_impl(iterator_impl impl = iterator_impl())
|
||||
: _impl(impl) {
|
||||
flat_multi_set_iterator_impl(
|
||||
iterator_impl impl = iterator_impl())
|
||||
: _impl(impl) {
|
||||
}
|
||||
template <typename other_iterator_impl>
|
||||
flat_multi_set_iterator_impl(
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &other) : _impl(other._impl) {
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
other_iterator_impl> &other)
|
||||
: _impl(other._impl) {
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
|
@ -91,10 +92,9 @@ public:
|
|||
}
|
||||
template <typename other_iterator_impl>
|
||||
difference_type operator-(
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl - right._impl;
|
||||
}
|
||||
reference operator[](difference_type offset) const {
|
||||
|
@ -103,37 +103,37 @@ public:
|
|||
|
||||
template <typename other_iterator_impl>
|
||||
bool operator==(
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl == right._impl;
|
||||
}
|
||||
template <typename other_iterator_impl>
|
||||
bool operator!=(
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl != right._impl;
|
||||
}
|
||||
template <typename other_iterator_impl>
|
||||
bool operator<(
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
other_iterator_impl> &right) const {
|
||||
const flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
other_iterator_impl> &right) const {
|
||||
return _impl < right._impl;
|
||||
}
|
||||
|
||||
private:
|
||||
iterator_impl _impl;
|
||||
friend class flat_multi_set<Type, Compare>;
|
||||
friend class flat_set<Type, Compare>;
|
||||
|
||||
template <typename OtherType, typename OtherCompare>
|
||||
friend class flat_multi_set;
|
||||
|
||||
template <typename OtherType, typename OtherCompare>
|
||||
friend class flat_set;
|
||||
|
||||
template <
|
||||
typename OtherType,
|
||||
typename OtherCompare,
|
||||
typename other_iterator_impl>
|
||||
friend class flat_multi_set_iterator_impl;
|
||||
|
||||
|
@ -143,159 +143,111 @@ private:
|
|||
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class flat_multi_set_const_wrap {
|
||||
public:
|
||||
constexpr flat_multi_set_const_wrap(const Type &value)
|
||||
: _value(value) {
|
||||
}
|
||||
constexpr flat_multi_set_const_wrap(Type &&value)
|
||||
: _value(std::move(value)) {
|
||||
}
|
||||
inline constexpr operator const Type&() const {
|
||||
return _value;
|
||||
}
|
||||
constexpr Type &wrapped() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
Type _value;
|
||||
|
||||
};
|
||||
|
||||
template <typename Type, typename Compare>
|
||||
class flat_multi_set {
|
||||
class const_wrap {
|
||||
public:
|
||||
constexpr const_wrap(const Type &value)
|
||||
: _value(value) {
|
||||
}
|
||||
constexpr const_wrap(Type &&value)
|
||||
: _value(std::move(value)) {
|
||||
}
|
||||
inline constexpr operator const Type&() const {
|
||||
return _value;
|
||||
}
|
||||
constexpr Type &wrapped() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
Type _value;
|
||||
|
||||
};
|
||||
|
||||
class compare {
|
||||
public:
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType1>, const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType2>, const_wrap>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &b) const {
|
||||
return Compare()(
|
||||
std::forward<OtherType1>(a),
|
||||
std::forward<OtherType2>(b));
|
||||
}
|
||||
inline constexpr auto operator()(
|
||||
const const_wrap &a,
|
||||
const const_wrap &b) const {
|
||||
return operator()(
|
||||
static_cast<const Type&>(a),
|
||||
static_cast<const Type&>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
||||
inline constexpr auto operator()(
|
||||
const const_wrap &a,
|
||||
OtherType &&b) const {
|
||||
return operator()(
|
||||
static_cast<const Type&>(a),
|
||||
std::forward<OtherType>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType &&a,
|
||||
const const_wrap &b) const {
|
||||
return operator()(
|
||||
std::forward<OtherType>(a),
|
||||
static_cast<const Type&>(b));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using impl = std::deque<const_wrap>;
|
||||
using const_wrap = flat_multi_set_const_wrap<Type>;
|
||||
using impl_t = std::deque<const_wrap>;
|
||||
|
||||
public:
|
||||
using value_type = Type;
|
||||
using size_type = typename impl::size_type;
|
||||
using difference_type = typename impl::difference_type;
|
||||
using size_type = typename impl_t::size_type;
|
||||
using difference_type = typename impl_t::difference_type;
|
||||
using pointer = const Type*;
|
||||
using reference = const Type&;
|
||||
|
||||
using iterator = flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::iterator>;
|
||||
typename impl_t::iterator>;
|
||||
using const_iterator = flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::const_iterator>;
|
||||
typename impl_t::const_iterator>;
|
||||
using reverse_iterator = flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::reverse_iterator>;
|
||||
typename impl_t::reverse_iterator>;
|
||||
using const_reverse_iterator = flat_multi_set_iterator_impl<
|
||||
Type,
|
||||
Compare,
|
||||
typename impl::const_reverse_iterator>;
|
||||
typename impl_t::const_reverse_iterator>;
|
||||
|
||||
flat_multi_set() = default;
|
||||
|
||||
template <
|
||||
typename Iterator,
|
||||
typename = typename std::iterator_traits<Iterator>::iterator_category>
|
||||
flat_multi_set(Iterator first, Iterator last) : _impl(first, last) {
|
||||
base::sort(_impl, compare());
|
||||
flat_multi_set(Iterator first, Iterator last)
|
||||
: _data(first, last) {
|
||||
std::sort(std::begin(impl()), std::end(impl()), compare());
|
||||
}
|
||||
|
||||
flat_multi_set(std::initializer_list<Type> iter)
|
||||
: flat_multi_set(iter.begin(), iter.end()) {
|
||||
: flat_multi_set(iter.begin(), iter.end()) {
|
||||
}
|
||||
|
||||
size_type size() const {
|
||||
return _impl.size();
|
||||
return impl().size();
|
||||
}
|
||||
bool empty() const {
|
||||
return _impl.empty();
|
||||
return impl().empty();
|
||||
}
|
||||
void clear() {
|
||||
_impl.clear();
|
||||
impl().clear();
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return _impl.begin();
|
||||
return impl().begin();
|
||||
}
|
||||
iterator end() {
|
||||
return _impl.end();
|
||||
return impl().end();
|
||||
}
|
||||
const_iterator begin() const {
|
||||
return _impl.begin();
|
||||
return impl().begin();
|
||||
}
|
||||
const_iterator end() const {
|
||||
return _impl.end();
|
||||
return impl().end();
|
||||
}
|
||||
const_iterator cbegin() const {
|
||||
return _impl.cbegin();
|
||||
return impl().cbegin();
|
||||
}
|
||||
const_iterator cend() const {
|
||||
return _impl.cend();
|
||||
return impl().cend();
|
||||
}
|
||||
reverse_iterator rbegin() {
|
||||
return _impl.rbegin();
|
||||
return impl().rbegin();
|
||||
}
|
||||
reverse_iterator rend() {
|
||||
return _impl.rend();
|
||||
return impl().rend();
|
||||
}
|
||||
const_reverse_iterator rbegin() const {
|
||||
return _impl.rbegin();
|
||||
return impl().rbegin();
|
||||
}
|
||||
const_reverse_iterator rend() const {
|
||||
return _impl.rend();
|
||||
return impl().rend();
|
||||
}
|
||||
const_reverse_iterator crbegin() const {
|
||||
return _impl.crbegin();
|
||||
return impl().crbegin();
|
||||
}
|
||||
const_reverse_iterator crend() const {
|
||||
return _impl.crend();
|
||||
return impl().crend();
|
||||
}
|
||||
|
||||
reference front() const {
|
||||
|
@ -307,25 +259,25 @@ public:
|
|||
|
||||
iterator insert(const Type &value) {
|
||||
if (empty() || compare()(value, front())) {
|
||||
_impl.push_front(value);
|
||||
impl().push_front(value);
|
||||
return begin();
|
||||
} else if (!compare()(value, back())) {
|
||||
_impl.push_back(value);
|
||||
impl().push_back(value);
|
||||
return (end() - 1);
|
||||
}
|
||||
auto where = getUpperBound(value);
|
||||
return _impl.insert(where, value);
|
||||
return impl().insert(where, value);
|
||||
}
|
||||
iterator insert(Type &&value) {
|
||||
if (empty() || compare()(value, front())) {
|
||||
_impl.push_front(std::move(value));
|
||||
impl().push_front(std::move(value));
|
||||
return begin();
|
||||
} else if (!compare()(value, back())) {
|
||||
_impl.push_back(std::move(value));
|
||||
impl().push_back(std::move(value));
|
||||
return (end() - 1);
|
||||
}
|
||||
auto where = getUpperBound(value);
|
||||
return _impl.insert(where, std::move(value));
|
||||
return impl().insert(where, std::move(value));
|
||||
}
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args) {
|
||||
|
@ -342,7 +294,7 @@ public:
|
|||
if (compare()(value, *where)) {
|
||||
return false;
|
||||
}
|
||||
_impl.erase(where);
|
||||
impl().erase(where);
|
||||
return true;
|
||||
}
|
||||
int removeAll(const Type &value) {
|
||||
|
@ -355,15 +307,15 @@ public:
|
|||
if (range.first == range.second) {
|
||||
return 0;
|
||||
}
|
||||
_impl.erase(range.first, range.second);
|
||||
impl().erase(range.first, range.second);
|
||||
return (range.second - range.first);
|
||||
}
|
||||
|
||||
iterator erase(const_iterator where) {
|
||||
return _impl.erase(where._impl);
|
||||
return impl().erase(where._impl);
|
||||
}
|
||||
iterator erase(const_iterator from, const_iterator till) {
|
||||
return _impl.erase(from._impl, till._impl);
|
||||
return impl().erase(from._impl, till._impl);
|
||||
}
|
||||
|
||||
iterator findFirst(const Type &value) {
|
||||
|
@ -373,7 +325,7 @@ public:
|
|||
return end();
|
||||
}
|
||||
auto where = getLowerBound(value);
|
||||
return compare()(value, *where) ? _impl.end() : where;
|
||||
return compare()(value, *where) ? impl().end() : where;
|
||||
}
|
||||
|
||||
const_iterator findFirst(const Type &value) const {
|
||||
|
@ -383,33 +335,33 @@ public:
|
|||
return end();
|
||||
}
|
||||
auto where = getLowerBound(value);
|
||||
return compare()(value, *where) ? _impl.end() : where;
|
||||
return compare()(value, *where) ? impl().end() : where;
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = typename Compare::is_transparent>
|
||||
iterator findFirst(const OtherType &value) {
|
||||
iterator findFirst(const OtherType &value) {
|
||||
if (empty()
|
||||
|| compare()(value, front())
|
||||
|| compare()(back(), value)) {
|
||||
return end();
|
||||
}
|
||||
auto where = getLowerBound(value);
|
||||
return compare()(value, *where) ? _impl.end() : where;
|
||||
return compare()(value, *where) ? impl().end() : where;
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = typename Compare::is_transparent>
|
||||
const_iterator findFirst(const OtherType &value) const {
|
||||
const_iterator findFirst(const OtherType &value) const {
|
||||
if (empty()
|
||||
|| compare()(value, front())
|
||||
|| compare()(back(), value)) {
|
||||
return end();
|
||||
}
|
||||
auto where = getLowerBound(value);
|
||||
return compare()(value, *where) ? _impl.end() : where;
|
||||
return compare()(value, *where) ? impl().end() : where;
|
||||
}
|
||||
|
||||
bool contains(const Type &value) const {
|
||||
|
@ -450,8 +402,8 @@ public:
|
|||
typename Iterator,
|
||||
typename = typename std::iterator_traits<Iterator>::iterator_category>
|
||||
void merge(Iterator first, Iterator last) {
|
||||
_impl.insert(_impl.end(), first, last);
|
||||
base::sort(_impl, compare());
|
||||
impl().insert(impl().end(), first, last);
|
||||
std::sort(std::begin(impl()), std::end(impl()), compare());
|
||||
}
|
||||
|
||||
void merge(const flat_multi_set<Type, Compare> &other) {
|
||||
|
@ -463,44 +415,149 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
impl _impl;
|
||||
friend class flat_set<Type, Compare>;
|
||||
|
||||
typename impl::iterator getLowerBound(const Type &value) {
|
||||
return base::lower_bound(_impl, value, compare());
|
||||
struct transparent_compare : Compare {
|
||||
inline constexpr const Compare &initial() const noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType1>, const_wrap> &&
|
||||
!std::is_same_v<std::decay_t<OtherType2>, const_wrap>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &&b) const {
|
||||
return initial()(
|
||||
std::forward<OtherType1>(a),
|
||||
std::forward<OtherType2>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType1,
|
||||
typename OtherType2>
|
||||
inline constexpr auto operator()(
|
||||
OtherType1 &&a,
|
||||
OtherType2 &&b) const -> std::enable_if_t<
|
||||
std::is_same_v<std::decay_t<OtherType1>, const_wrap> &&
|
||||
std::is_same_v<std::decay_t<OtherType2>, const_wrap>, bool> {
|
||||
return initial()(
|
||||
static_cast<const Type&>(a),
|
||||
static_cast<const Type&>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
||||
inline constexpr auto operator()(
|
||||
const const_wrap &a,
|
||||
OtherType &&b) const {
|
||||
return initial()(
|
||||
static_cast<const Type&>(a),
|
||||
std::forward<OtherType>(b));
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = std::enable_if_t<
|
||||
!std::is_same_v<std::decay_t<OtherType>, const_wrap>>>
|
||||
inline constexpr auto operator()(
|
||||
OtherType &&a,
|
||||
const const_wrap &b) const {
|
||||
return initial()(
|
||||
std::forward<OtherType>(a),
|
||||
static_cast<const Type&>(b));
|
||||
}
|
||||
|
||||
};
|
||||
struct Data : transparent_compare {
|
||||
template <typename ...Args>
|
||||
Data(Args &&...args)
|
||||
: elements(std::forward<Args>(args)...) {
|
||||
}
|
||||
|
||||
impl_t elements;
|
||||
};
|
||||
|
||||
Data _data;
|
||||
const transparent_compare &compare() const {
|
||||
return _data;
|
||||
}
|
||||
typename impl::const_iterator getLowerBound(const Type &value) const {
|
||||
return base::lower_bound(_impl, value, compare());
|
||||
const impl_t &impl() const {
|
||||
return _data.elements;
|
||||
}
|
||||
impl_t &impl() {
|
||||
return _data.elements;
|
||||
}
|
||||
|
||||
typename impl_t::iterator getLowerBound(const Type &value) {
|
||||
return std::lower_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
typename impl_t::const_iterator getLowerBound(const Type &value) const {
|
||||
return std::lower_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = typename Compare::is_transparent>
|
||||
typename impl::iterator getLowerBound(const OtherType &value) {
|
||||
return base::lower_bound(_impl, value, compare());
|
||||
typename impl_t::iterator getLowerBound(const OtherType &value) {
|
||||
return std::lower_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
template <
|
||||
typename OtherType,
|
||||
typename = typename Compare::is_transparent>
|
||||
typename impl::const_iterator getLowerBound(const OtherType &value) const {
|
||||
return base::lower_bound(_impl, value, compare());
|
||||
typename impl_t::const_iterator getLowerBound(const OtherType &value) const {
|
||||
return std::lower_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
typename impl::iterator getUpperBound(const Type &value) {
|
||||
return base::upper_bound(_impl, value, compare());
|
||||
typename impl_t::iterator getUpperBound(const Type &value) {
|
||||
return std::upper_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
typename impl::const_iterator getUpperBound(const Type &value) const {
|
||||
return base::upper_bound(_impl, value, compare());
|
||||
typename impl_t::const_iterator getUpperBound(const Type &value) const {
|
||||
return std::upper_bound(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
std::pair<
|
||||
typename impl::iterator,
|
||||
typename impl::iterator
|
||||
typename impl_t::iterator,
|
||||
typename impl_t::iterator
|
||||
> getEqualRange(const Type &value) {
|
||||
return base::equal_range(_impl, value, compare());
|
||||
return std::equal_range(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
std::pair<
|
||||
typename impl::const_iterator,
|
||||
typename impl::const_iterator
|
||||
typename impl_t::const_iterator,
|
||||
typename impl_t::const_iterator
|
||||
> getEqualRange(const Type &value) const {
|
||||
return base::equal_range(_impl, value, compare());
|
||||
return std::equal_range(
|
||||
std::begin(impl()),
|
||||
std::end(impl()),
|
||||
value,
|
||||
compare());
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -508,7 +565,6 @@ private:
|
|||
template <typename Type, typename Compare>
|
||||
class flat_set : private flat_multi_set<Type, Compare> {
|
||||
using parent = flat_multi_set<Type, Compare>;
|
||||
using compare = typename parent::compare;
|
||||
|
||||
public:
|
||||
using iterator = typename parent::iterator;
|
||||
|
@ -553,30 +609,30 @@ public:
|
|||
using parent::erase;
|
||||
|
||||
iterator insert(const Type &value) {
|
||||
if (this->empty() || compare()(value, this->front())) {
|
||||
this->_impl.push_front(value);
|
||||
if (this->empty() || this->compare()(value, this->front())) {
|
||||
this->impl().push_front(value);
|
||||
return this->begin();
|
||||
} else if (compare()(this->back(), value)) {
|
||||
this->_impl.push_back(value);
|
||||
} else if (this->compare()(this->back(), value)) {
|
||||
this->impl().push_back(value);
|
||||
return (this->end() - 1);
|
||||
}
|
||||
auto where = this->getLowerBound(value);
|
||||
if (compare()(value, *where)) {
|
||||
return this->_impl.insert(where, value);
|
||||
if (this->compare()(value, *where)) {
|
||||
return this->impl().insert(where, value);
|
||||
}
|
||||
return this->end();
|
||||
}
|
||||
iterator insert(Type &&value) {
|
||||
if (this->empty() || compare()(value, this->front())) {
|
||||
this->_impl.push_front(std::move(value));
|
||||
if (this->empty() || this->compare()(value, this->front())) {
|
||||
this->impl().push_front(std::move(value));
|
||||
return this->begin();
|
||||
} else if (compare()(this->back(), value)) {
|
||||
this->_impl.push_back(std::move(value));
|
||||
} else if (this->compare()(this->back(), value)) {
|
||||
this->impl().push_back(std::move(value));
|
||||
return (this->end() - 1);
|
||||
}
|
||||
auto where = this->getLowerBound(value);
|
||||
if (compare()(value, *where)) {
|
||||
return this->_impl.insert(where, std::move(value));
|
||||
if (this->compare()(value, *where)) {
|
||||
return this->impl().insert(where, std::move(value));
|
||||
}
|
||||
return this->end();
|
||||
}
|
||||
|
@ -612,9 +668,9 @@ public:
|
|||
void modify(iterator which, Action action) {
|
||||
action(which.wrapped());
|
||||
for (auto i = iterator(which + 1), e = end(); i != e; ++i) {
|
||||
if (compare()(*i, *which)) {
|
||||
if (this->compare()(*i, *which)) {
|
||||
std::swap(i.wrapped(), which.wrapped());
|
||||
} else if (!compare()(*which, *i)) {
|
||||
} else if (!this->compare()(*which, *i)) {
|
||||
erase(which);
|
||||
return;
|
||||
} else{
|
||||
|
@ -623,9 +679,9 @@ public:
|
|||
}
|
||||
for (auto i = which, b = begin(); i != b;) {
|
||||
--i;
|
||||
if (compare()(*which, *i)) {
|
||||
if (this->compare()(*which, *i)) {
|
||||
std::swap(i.wrapped(), which.wrapped());
|
||||
} else if (!compare()(*i, *which)) {
|
||||
} else if (!this->compare()(*i, *which)) {
|
||||
erase(which);
|
||||
return;
|
||||
} else {
|
||||
|
@ -652,12 +708,15 @@ public:
|
|||
|
||||
private:
|
||||
void finalize() {
|
||||
this->_impl.erase(
|
||||
this->impl().erase(
|
||||
std::unique(
|
||||
this->_impl.begin(),
|
||||
this->_impl.end(),
|
||||
[](auto &&a, auto &&b) { return !compare()(a, b); }),
|
||||
this->_impl.end());
|
||||
std::begin(this->impl()),
|
||||
std::end(this->impl()),
|
||||
[&](auto &&a, auto &&b) {
|
||||
return !this->compare()(a, b);
|
||||
}
|
||||
),
|
||||
std::end(this->impl()));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -22,7 +22,27 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
|
||||
#include "base/flat_set.h"
|
||||
|
||||
struct int_wrap {
|
||||
int value;
|
||||
};
|
||||
struct int_wrap_comparator {
|
||||
using is_transparent = void;
|
||||
inline bool operator()(const int &a, const int_wrap &b) const {
|
||||
return a < b.value;
|
||||
}
|
||||
inline bool operator()(const int_wrap &a, const int_wrap &b) const {
|
||||
return a.value < b.value;
|
||||
}
|
||||
inline bool operator()(const int_wrap &a, const int &b) const {
|
||||
return a.value < b;
|
||||
}
|
||||
inline bool operator()(const int &a, const int &b) const {
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
|
||||
|
||||
base::flat_set<int> v;
|
||||
v.insert(0);
|
||||
v.insert(5);
|
||||
|
@ -48,3 +68,30 @@ TEST_CASE("flat_sets should keep items sorted", "[flat_set]") {
|
|||
checkSorted();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("flat_sets with custom comparators", "[flat_set]") {
|
||||
base::flat_set<int_wrap, int_wrap_comparator> v;
|
||||
v.insert({ 0 });
|
||||
v.insert({ 5 });
|
||||
v.insert({ 4 });
|
||||
v.insert({ 2 });
|
||||
|
||||
REQUIRE(v.find(4) != v.end());
|
||||
|
||||
auto checkSorted = [&] {
|
||||
auto prev = v.begin();
|
||||
REQUIRE(prev != v.end());
|
||||
for (auto i = prev + 1; i != v.end(); prev = i, ++i) {
|
||||
REQUIRE(prev->value < i->value);
|
||||
}
|
||||
};
|
||||
REQUIRE(v.size() == 4);
|
||||
checkSorted();
|
||||
|
||||
SECTION("adding item puts it in the right position") {
|
||||
v.insert({ 3 });
|
||||
REQUIRE(v.size() == 5);
|
||||
REQUIRE(v.find(3) != v.end());
|
||||
checkSorted();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -593,8 +593,8 @@ void PeerListContent::addRowEntry(not_null<PeerListRow*> row) {
|
|||
|
||||
void PeerListContent::invalidatePixmapsCache() {
|
||||
auto invalidate = [](auto &&row) { row->invalidatePixmapsCache(); };
|
||||
base::for_each(_rows, invalidate);
|
||||
base::for_each(_searchRows, invalidate);
|
||||
ranges::for_each(_rows, invalidate);
|
||||
ranges::for_each(_searchRows, invalidate);
|
||||
}
|
||||
|
||||
bool PeerListContent::addingToSearchIndex() const {
|
||||
|
|
|
@ -648,11 +648,11 @@ void EditChatAdminsBoxController::rebuildRows() {
|
|||
admins.insert(admins.end(), others.begin(), others.end());
|
||||
others.clear();
|
||||
}
|
||||
auto sortByName = [](auto a, auto b) {
|
||||
auto sortByName = [](not_null<UserData*> a, auto b) {
|
||||
return (a->name.compare(b->name, Qt::CaseInsensitive) < 0);
|
||||
};
|
||||
base::sort(admins, sortByName);
|
||||
base::sort(others, sortByName);
|
||||
ranges::sort(admins, sortByName);
|
||||
ranges::sort(others, sortByName);
|
||||
|
||||
auto addOne = [this](not_null<UserData*> user) {
|
||||
if (auto row = createRow(user)) {
|
||||
|
@ -664,8 +664,8 @@ void EditChatAdminsBoxController::rebuildRows() {
|
|||
addOne(creator);
|
||||
}
|
||||
}
|
||||
base::for_each(admins, addOne);
|
||||
base::for_each(others, addOne);
|
||||
ranges::for_each(admins, addOne);
|
||||
ranges::for_each(others, addOne);
|
||||
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
|
|
@ -538,7 +538,7 @@ void Controller::usernameChanged() {
|
|||
_checkUsernameTimer.cancel();
|
||||
return;
|
||||
}
|
||||
auto bad = base::find_if(username, [](QChar ch) {
|
||||
auto bad = ranges::find_if(username, [](QChar ch) {
|
||||
return (ch < 'A' || ch > 'Z')
|
||||
&& (ch < 'a' || ch > 'z')
|
||||
&& (ch < '0' || ch > '9')
|
||||
|
|
|
@ -51,10 +51,10 @@ public:
|
|||
bool canAddItem(not_null<const HistoryItem*> item) const {
|
||||
return (ComputeType(item) == _type && item->date.date() == _date);
|
||||
}
|
||||
void addItem(HistoryItem *item) {
|
||||
void addItem(not_null<HistoryItem*> item) {
|
||||
Expects(canAddItem(item));
|
||||
_items.push_back(item);
|
||||
base::sort(_items, [](HistoryItem *a, HistoryItem *b) {
|
||||
ranges::sort(_items, [](not_null<HistoryItem*> a, auto b) {
|
||||
return (a->id > b->id);
|
||||
});
|
||||
refreshStatus();
|
||||
|
@ -116,7 +116,7 @@ private:
|
|||
void refreshStatus();
|
||||
static Type ComputeType(not_null<const HistoryItem*> item);
|
||||
|
||||
std::vector<HistoryItem*> _items;
|
||||
std::vector<not_null<HistoryItem*>> _items;
|
||||
QDate _date;
|
||||
Type _type;
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ base::optional<int> SparseIdsSlice::distance(
|
|||
}
|
||||
|
||||
base::optional<MsgId> SparseIdsSlice::nearest(MsgId msgId) const {
|
||||
if (auto it = base::lower_bound(_ids, msgId); it != _ids.end()) {
|
||||
if (auto it = ranges::lower_bound(_ids, msgId); it != _ids.end()) {
|
||||
return *it;
|
||||
} else if (_ids.empty()) {
|
||||
return base::none;
|
||||
|
@ -342,7 +342,7 @@ void SparseIdsSliceBuilder::sliceToLimits() {
|
|||
return;
|
||||
}
|
||||
auto requestedSomething = false;
|
||||
auto aroundIt = base::lower_bound(_ids, _key);
|
||||
auto aroundIt = ranges::lower_bound(_ids, _key);
|
||||
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
||||
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
||||
if (removeFromBegin > 0) {
|
||||
|
|
|
@ -60,7 +60,8 @@ private:
|
|||
|
||||
};
|
||||
|
||||
UserPhotosSlice::UserPhotosSlice(Key key) : UserPhotosSlice(
|
||||
UserPhotosSlice::UserPhotosSlice(Key key)
|
||||
: UserPhotosSlice(
|
||||
key,
|
||||
{},
|
||||
base::none,
|
||||
|
@ -74,15 +75,15 @@ UserPhotosSlice::UserPhotosSlice(
|
|||
base::optional<int> fullCount,
|
||||
base::optional<int> skippedBefore,
|
||||
int skippedAfter)
|
||||
: _key(key)
|
||||
, _ids(ids)
|
||||
, _fullCount(fullCount)
|
||||
, _skippedBefore(skippedBefore)
|
||||
, _skippedAfter(skippedAfter) {
|
||||
: _key(key)
|
||||
, _ids(ids)
|
||||
, _fullCount(fullCount)
|
||||
, _skippedBefore(skippedBefore)
|
||||
, _skippedAfter(skippedAfter) {
|
||||
}
|
||||
|
||||
base::optional<int> UserPhotosSlice::indexOf(PhotoId photoId) const {
|
||||
auto it = base::find(_ids, photoId);
|
||||
auto it = ranges::find(_ids, photoId);
|
||||
if (it != _ids.end()) {
|
||||
return (it - _ids.begin());
|
||||
}
|
||||
|
@ -190,7 +191,7 @@ void UserPhotosSliceBuilder::mergeSliceData(
|
|||
}
|
||||
|
||||
void UserPhotosSliceBuilder::sliceToLimits() {
|
||||
auto aroundIt = base::find(_ids, _key.photoId);
|
||||
auto aroundIt = ranges::find(_ids, _key.photoId);
|
||||
auto removeFromBegin = (aroundIt - _ids.begin() - _limitBefore);
|
||||
auto removeFromEnd = (_ids.end() - aroundIt - _limitAfter - 1);
|
||||
if (removeFromEnd > 0) {
|
||||
|
|
|
@ -73,7 +73,7 @@ QString TopBarOverride::generateText() const {
|
|||
}
|
||||
|
||||
bool TopBarOverride::computeCanDelete() const {
|
||||
return base::find_if(_items.list, [](const SelectedItem &item) {
|
||||
return ranges::find_if(_items.list, [](const SelectedItem &item) {
|
||||
return !item.canDelete;
|
||||
}) == _items.list.end();
|
||||
}
|
||||
|
|
|
@ -104,6 +104,10 @@ public:
|
|||
return _height;
|
||||
}
|
||||
|
||||
int bottom() const {
|
||||
return top() + height();
|
||||
}
|
||||
|
||||
bool removeItem(UniversalMsgId universalId);
|
||||
FoundItem findItemNearId(UniversalMsgId universalId) const;
|
||||
FoundItem findItemByPoint(QPoint point) const;
|
||||
|
@ -302,12 +306,11 @@ auto ListWidget::Section::findItemByPoint(
|
|||
auto ListWidget::Section::findItemNearId(
|
||||
UniversalMsgId universalId) const -> FoundItem {
|
||||
Expects(!_items.empty());
|
||||
auto itemIt = base::lower_bound(
|
||||
auto itemIt = ranges::lower_bound(
|
||||
_items,
|
||||
universalId,
|
||||
[this](const auto &item, UniversalMsgId universalId) {
|
||||
return (item.first > universalId);
|
||||
});
|
||||
std::greater<>(),
|
||||
[](const auto &item) -> UniversalMsgId { return item.first; });
|
||||
if (itemIt == _items.end()) {
|
||||
--itemIt;
|
||||
}
|
||||
|
@ -318,36 +321,39 @@ auto ListWidget::Section::findItemNearId(
|
|||
|
||||
auto ListWidget::Section::findItemAfterTop(
|
||||
int top) -> Items::iterator {
|
||||
return base::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
_items,
|
||||
top,
|
||||
[this](const auto &item, int top) {
|
||||
std::less_equal<>(),
|
||||
[this](const auto &item) {
|
||||
auto itemTop = item.second->position() / _itemsInRow;
|
||||
return (itemTop + item.second->height()) <= top;
|
||||
return itemTop + item.second->height();
|
||||
});
|
||||
}
|
||||
|
||||
auto ListWidget::Section::findItemAfterTop(
|
||||
int top) const -> Items::const_iterator {
|
||||
return base::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
_items,
|
||||
top,
|
||||
[this](const auto &item, int top) {
|
||||
auto itemTop = item.second->position() / _itemsInRow;
|
||||
return (itemTop + item.second->height()) <= top;
|
||||
});
|
||||
std::less_equal<>(),
|
||||
[this](const auto &item) {
|
||||
auto itemTop = item.second->position() / _itemsInRow;
|
||||
return itemTop + item.second->height();
|
||||
});
|
||||
}
|
||||
|
||||
auto ListWidget::Section::findItemAfterBottom(
|
||||
Items::const_iterator from,
|
||||
int bottom) const -> Items::const_iterator {
|
||||
return std::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
from,
|
||||
_items.end(),
|
||||
bottom,
|
||||
[this](const auto &item, int bottom) {
|
||||
std::less<>(),
|
||||
[this](const auto &item) {
|
||||
auto itemTop = item.second->position() / _itemsInRow;
|
||||
return itemTop < bottom;
|
||||
return itemTop;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1182,12 +1188,12 @@ void ListWidget::showContextMenu(
|
|||
}
|
||||
|
||||
auto canDeleteAll = [&] {
|
||||
return base::find_if(_selected, [](auto &item) {
|
||||
return ranges::find_if(_selected, [](auto &&item) {
|
||||
return !item.second.canDelete;
|
||||
}) == _selected.end();
|
||||
};
|
||||
auto canForwardAll = [&] {
|
||||
return base::find_if(_selected, [](auto &item) {
|
||||
return ranges::find_if(_selected, [](auto &&item) {
|
||||
return !item.second.canForward;
|
||||
}) == _selected.end();
|
||||
};
|
||||
|
@ -2042,44 +2048,40 @@ void ListWidget::clearStaleLayouts() {
|
|||
|
||||
auto ListWidget::findSectionByItem(
|
||||
UniversalMsgId universalId) -> std::vector<Section>::iterator {
|
||||
return base::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
_sections,
|
||||
universalId,
|
||||
[](const Section §ion, int universalId) {
|
||||
return section.minId() > universalId;
|
||||
});
|
||||
std::greater<>(),
|
||||
[](const Section §ion) { return section.minId(); });
|
||||
}
|
||||
|
||||
auto ListWidget::findSectionAfterTop(
|
||||
int top) -> std::vector<Section>::iterator {
|
||||
return base::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
_sections,
|
||||
top,
|
||||
[](const Section §ion, int top) {
|
||||
return (section.top() + section.height()) <= top;
|
||||
});
|
||||
std::less_equal<>(),
|
||||
[](const Section §ion) { return section.bottom(); });
|
||||
}
|
||||
|
||||
auto ListWidget::findSectionAfterTop(
|
||||
int top) const -> std::vector<Section>::const_iterator {
|
||||
return base::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
_sections,
|
||||
top,
|
||||
[](const Section §ion, int top) {
|
||||
return (section.top() + section.height()) <= top;
|
||||
});
|
||||
std::less_equal<>(),
|
||||
[](const Section §ion) { return section.bottom(); });
|
||||
}
|
||||
|
||||
auto ListWidget::findSectionAfterBottom(
|
||||
std::vector<Section>::const_iterator from,
|
||||
int bottom) const -> std::vector<Section>::const_iterator {
|
||||
return std::lower_bound(
|
||||
return ranges::lower_bound(
|
||||
from,
|
||||
_sections.end(),
|
||||
bottom,
|
||||
[](const Section §ion, int bottom) {
|
||||
return section.top() < bottom;
|
||||
});
|
||||
std::less<>(),
|
||||
[](const Section §ion) { return section.top(); });
|
||||
}
|
||||
|
||||
ListWidget::~ListWidget() = default;
|
||||
|
|
|
@ -341,7 +341,7 @@ DcOptions::Ids DcOptions::configEnumDcIds() const {
|
|||
}
|
||||
}
|
||||
}
|
||||
base::sort(result);
|
||||
ranges::sort(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ bool UnsafeShowOpenWithDropdown(const QString &filepath, QPoint menuPosition) {
|
|||
|
||||
if (!handlers.empty()) {
|
||||
HMENU menu = CreatePopupMenu();
|
||||
base::sort(handlers, [](const OpenWithApp &a, const OpenWithApp &b) {
|
||||
ranges::sort(handlers, [](const OpenWithApp &a, auto &b) {
|
||||
return a.name() < b.name();
|
||||
});
|
||||
for (int32 i = 0, l = handlers.size(); i < l; ++i) {
|
||||
|
|
|
@ -277,13 +277,13 @@ std::unique_ptr<PeerListState> ParticipantsBoxController::saveState() {
|
|||
return;
|
||||
}
|
||||
}
|
||||
auto pos = base::find(weak->list, user);
|
||||
auto pos = ranges::find(weak->list, user);
|
||||
if (pos == weak->list.cend()) {
|
||||
weak->list.push_back(user);
|
||||
}
|
||||
base::stable_partition(weak->list, [user](not_null<PeerData*> peer) {
|
||||
return (peer == user);
|
||||
});
|
||||
ranges::stable_partition(
|
||||
weak->list,
|
||||
[user](auto peer) { return (peer == user); });
|
||||
}, my->lifetime);
|
||||
Auth().data().megagroupParticipantRemoved(_channel)
|
||||
| rpl::start_with_next([weak](not_null<UserData*> user) {
|
||||
|
|
|
@ -326,7 +326,7 @@ inline auto combine(
|
|||
state->latest.push_back(
|
||||
std::move(*value));
|
||||
}
|
||||
base::take(state->accumulated);
|
||||
details::take(state->accumulated);
|
||||
consumer.put_next_copy(state->latest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ template <typename Value, typename Error>
|
|||
inline void type_erased_handlers<Value, Error>::terminate() {
|
||||
if (!_terminated) {
|
||||
_terminated = true;
|
||||
base::take(_lifetime).destroy();
|
||||
details::take(_lifetime).destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include <rpl/then.h>
|
||||
#include <rpl/range.h>
|
||||
#include <algorithm>
|
||||
#include "base/algorithm.h"
|
||||
#include "base/assertion.h"
|
||||
#include "base/index_based_iterator.h"
|
||||
|
||||
|
@ -54,8 +53,9 @@ public:
|
|||
if (auto strong = weak.lock()) {
|
||||
auto result = [weak, consumer] {
|
||||
if (auto strong = weak.lock()) {
|
||||
auto it = base::find(
|
||||
strong->consumers,
|
||||
auto it = std::find(
|
||||
strong->consumers.begin(),
|
||||
strong->consumers.end(),
|
||||
consumer);
|
||||
if (it != strong->consumers.end()) {
|
||||
it->terminate();
|
||||
|
@ -94,13 +94,13 @@ inline event_stream<Value>::event_stream() {
|
|||
|
||||
template <typename Value>
|
||||
inline event_stream<Value>::event_stream(event_stream &&other)
|
||||
: _data(base::take(other._data)) {
|
||||
: _data(details::take(other._data)) {
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
inline event_stream<Value> &event_stream<Value>::operator=(
|
||||
event_stream &&other) {
|
||||
_data = base::take(other._data);
|
||||
_data = details::take(other._data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ inline auto event_stream<Value>::weak() const
|
|||
|
||||
template <typename Value>
|
||||
inline event_stream<Value>::~event_stream() {
|
||||
if (auto data = base::take(_data)) {
|
||||
if (auto data = details::take(_data)) {
|
||||
for (auto &consumer : data->consumers) {
|
||||
consumer.put_done();
|
||||
}
|
||||
|
|
|
@ -21,10 +21,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#pragma once
|
||||
|
||||
#include "base/lambda.h"
|
||||
#include "base/algorithm.h"
|
||||
#include <deque>
|
||||
|
||||
namespace rpl {
|
||||
namespace details {
|
||||
|
||||
template <typename Type>
|
||||
inline Type take(Type &value) {
|
||||
return std::exchange(value, Type{});
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
class lifetime {
|
||||
public:
|
||||
|
@ -47,7 +54,7 @@ public:
|
|||
auto result = new Type(std::forward<Args>(args)...);
|
||||
add([result]() mutable {
|
||||
static_assert(sizeof(Type) > 0, "Can't delete unknown type.");
|
||||
delete base::take(result);
|
||||
delete details::take(result);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
@ -60,7 +67,7 @@ private:
|
|||
};
|
||||
|
||||
inline lifetime::lifetime(lifetime &&other)
|
||||
: _callbacks(base::take(other._callbacks)) {
|
||||
: _callbacks(details::take(other._callbacks)) {
|
||||
}
|
||||
|
||||
inline lifetime &lifetime::operator=(lifetime &&other) {
|
||||
|
@ -80,7 +87,7 @@ inline void lifetime::add(Destroy &&destroy) {
|
|||
}
|
||||
|
||||
inline void lifetime::add(lifetime &&other) {
|
||||
auto callbacks = base::take(other._callbacks);
|
||||
auto callbacks = details::take(other._callbacks);
|
||||
_callbacks.insert(
|
||||
_callbacks.begin(),
|
||||
std::make_move_iterator(callbacks.begin()),
|
||||
|
@ -88,7 +95,7 @@ inline void lifetime::add(lifetime &&other) {
|
|||
}
|
||||
|
||||
inline void lifetime::destroy() {
|
||||
for (auto &callback : base::take(_callbacks)) {
|
||||
for (auto &callback : details::take(_callbacks)) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ public:
|
|||
}
|
||||
}
|
||||
InvokeCounter(InvokeCounter &&other)
|
||||
: _copyCounter(base::take(other._copyCounter))
|
||||
, _moveCounter(base::take(other._moveCounter)) {
|
||||
: _copyCounter(details::take(other._copyCounter))
|
||||
, _moveCounter(details::take(other._moveCounter)) {
|
||||
if (_moveCounter) {
|
||||
++*_moveCounter;
|
||||
}
|
||||
|
@ -72,8 +72,8 @@ public:
|
|||
return *this;
|
||||
}
|
||||
InvokeCounter &operator=(InvokeCounter &&other) {
|
||||
_copyCounter = base::take(other._copyCounter);
|
||||
_moveCounter = base::take(other._moveCounter);
|
||||
_copyCounter = details::take(other._copyCounter);
|
||||
_moveCounter = details::take(other._moveCounter);
|
||||
if (_moveCounter) {
|
||||
++*_moveCounter;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ TEST_CASE("basic operators tests", "[rpl::operators]") {
|
|||
}
|
||||
REQUIRE(*sum == "1 1 3 ");
|
||||
}
|
||||
|
||||
|
||||
SECTION("filter tuple test") {
|
||||
auto sum = std::make_shared<std::string>("");
|
||||
{
|
||||
|
|
|
@ -80,14 +80,16 @@ int SparseIdsList::addRangeItemsAndCountNew(
|
|||
return 0;
|
||||
}
|
||||
|
||||
auto uniteFrom = base::lower_bound(
|
||||
auto uniteFrom = ranges::lower_bound(
|
||||
_slices,
|
||||
noSkipRange.from,
|
||||
[](const Slice &slice, MsgId from) { return slice.range.till < from; });
|
||||
auto uniteTill = base::upper_bound(
|
||||
std::less<>(),
|
||||
[](const Slice &slice) { return slice.range.till; });
|
||||
auto uniteTill = ranges::upper_bound(
|
||||
_slices,
|
||||
noSkipRange.till,
|
||||
[](MsgId till, const Slice &slice) { return till < slice.range.from; });
|
||||
std::less<>(),
|
||||
[](const Slice &slice) { return slice.range.from; });
|
||||
if (uniteFrom < uniteTill) {
|
||||
return uniteAndAdd(update, uniteFrom, uniteTill, messages, noSkipRange);
|
||||
}
|
||||
|
@ -151,10 +153,11 @@ void SparseIdsList::addSlice(
|
|||
}
|
||||
|
||||
void SparseIdsList::removeOne(MsgId messageId) {
|
||||
auto slice = base::lower_bound(
|
||||
auto slice = ranges::lower_bound(
|
||||
_slices,
|
||||
messageId,
|
||||
[](const Slice &slice, MsgId from) { return slice.range.till < from; });
|
||||
std::less<>(),
|
||||
[](const Slice &slice) { return slice.range.till; });
|
||||
if (slice != _slices.end() && slice->range.from <= messageId) {
|
||||
_slices.modify(slice, [messageId](Slice &slice) {
|
||||
return slice.messages.remove(messageId);
|
||||
|
@ -175,12 +178,11 @@ rpl::producer<SparseIdsListResult> SparseIdsList::query(
|
|||
SparseIdsListQuery &&query) const {
|
||||
return [this, query = std::move(query)](auto consumer) {
|
||||
auto slice = query.aroundId
|
||||
? base::lower_bound(
|
||||
? ranges::lower_bound(
|
||||
_slices,
|
||||
query.aroundId,
|
||||
[](const Slice &slice, MsgId id) {
|
||||
return slice.range.till < id;
|
||||
})
|
||||
std::less<>(),
|
||||
[](const Slice &slice) { return slice.range.till; })
|
||||
: _slices.end();
|
||||
if (slice != _slices.end()
|
||||
&& slice->range.from <= query.aroundId) {
|
||||
|
@ -199,7 +201,7 @@ SparseIdsListResult SparseIdsList::queryFromSlice(
|
|||
const SparseIdsListQuery &query,
|
||||
const Slice &slice) const {
|
||||
auto result = SparseIdsListResult {};
|
||||
auto position = base::lower_bound(slice.messages, query.aroundId);
|
||||
auto position = ranges::lower_bound(slice.messages, query.aroundId);
|
||||
auto haveBefore = int(position - slice.messages.begin());
|
||||
auto haveEqualOrAfter = int(slice.messages.end() - position);
|
||||
auto before = qMin(haveBefore, query.limitBefore);
|
||||
|
|
|
@ -51,7 +51,7 @@ void UserPhotos::List::addSlice(
|
|||
}
|
||||
|
||||
void UserPhotos::List::removeOne(PhotoId photoId) {
|
||||
auto position = base::find(_photoIds, photoId);
|
||||
auto position = ranges::find(_photoIds, photoId);
|
||||
if (position == _photoIds.end()) {
|
||||
_count = base::none;
|
||||
} else {
|
||||
|
@ -64,7 +64,7 @@ void UserPhotos::List::removeOne(PhotoId photoId) {
|
|||
}
|
||||
|
||||
void UserPhotos::List::removeAfter(PhotoId photoId) {
|
||||
auto position = base::find(_photoIds, photoId);
|
||||
auto position = ranges::find(_photoIds, photoId);
|
||||
if (position == _photoIds.end()) {
|
||||
_count = base::none;
|
||||
_photoIds.clear();
|
||||
|
@ -90,7 +90,7 @@ rpl::producer<UserPhotosResult> UserPhotos::List::query(
|
|||
auto result = UserPhotosResult {};
|
||||
result.count = _count;
|
||||
|
||||
auto position = base::find(_photoIds, query.key.photoId);
|
||||
auto position = ranges::find(_photoIds, query.key.photoId);
|
||||
if (position != _photoIds.end()) {
|
||||
auto haveBefore = int(position - _photoIds.begin());
|
||||
auto haveEqualOrAfter = int(_photoIds.end() - position);
|
||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
|||
#include "ui/wrap/slide_wrap.h"
|
||||
|
||||
#include <rpl/combine.h>
|
||||
#include <range/v3/algorithm/find.hpp>
|
||||
|
||||
namespace Ui {
|
||||
|
||||
|
@ -156,7 +157,7 @@ rpl::producer<bool> MultiSlideTracker::atLeastOneShownValue() const {
|
|||
return rpl::combine(
|
||||
std::move(shown),
|
||||
[](const std::vector<bool> &values) {
|
||||
return base::find(values, true) != values.end();
|
||||
return ranges::find(values, true) != values.end();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ RpWidget *VerticalLayout::addChild(
|
|||
}
|
||||
|
||||
void VerticalLayout::childHeightUpdated(RpWidget *child) {
|
||||
auto it = base::find_if(_rows, [child](const Row &row) {
|
||||
auto it = ranges::find_if(_rows, [child](const Row &row) {
|
||||
return (row.widget == child);
|
||||
});
|
||||
|
||||
|
@ -158,7 +158,7 @@ void VerticalLayout::childHeightUpdated(RpWidget *child) {
|
|||
}
|
||||
|
||||
void VerticalLayout::removeChild(RpWidget *child) {
|
||||
auto it = base::find_if(_rows, [child](const Row &row) {
|
||||
auto it = ranges::find_if(_rows, [child](const Row &row) {
|
||||
return (row.widget == child);
|
||||
});
|
||||
auto end = _rows.end();
|
||||
|
|
|
@ -386,17 +386,23 @@ int Completer::findEqualCharsCount(int position, const utf16string *word) {
|
|||
|
||||
std::vector<Suggestion> Completer::prepareResult() {
|
||||
auto firstCharOfQuery = _query[0];
|
||||
base::stable_partition(_result, [firstCharOfQuery](Result &result) {
|
||||
auto reorder = [&](auto &&predicate) {
|
||||
std::stable_partition(
|
||||
std::begin(_result),
|
||||
std::end(_result),
|
||||
std::forward<decltype(predicate)>(predicate));
|
||||
};
|
||||
reorder([firstCharOfQuery](Result &result) {
|
||||
auto firstCharAfterColon = result.replacement->replacement[1];
|
||||
return (firstCharAfterColon == firstCharOfQuery);
|
||||
});
|
||||
base::stable_partition(_result, [](Result &result) {
|
||||
reorder([](Result &result) {
|
||||
return (result.wordsUsed < 2);
|
||||
});
|
||||
base::stable_partition(_result, [](Result &result) {
|
||||
reorder([](Result &result) {
|
||||
return (result.wordsUsed < 3);
|
||||
});
|
||||
base::stable_partition(_result, [this](Result &result) {
|
||||
reorder([&](Result &result) {
|
||||
return isExactMatch(result.replacement->replacement);
|
||||
});
|
||||
|
||||
|
@ -412,13 +418,19 @@ std::vector<Suggestion> Completer::prepareResult() {
|
|||
}
|
||||
|
||||
string_span Completer::findWordsStartingWith(utf16char ch) {
|
||||
auto begin = base::lower_bound(_currentItemWords, ch, [](utf16string word, utf16char ch) {
|
||||
return word[0] < ch;
|
||||
});
|
||||
auto end = base::upper_bound(_currentItemWords, ch, [](utf16char ch, utf16string word) {
|
||||
return ch < word[0];
|
||||
});
|
||||
return _currentItemWords.subspan(begin - _currentItemWords.begin(), end - begin);
|
||||
auto begin = std::lower_bound(
|
||||
std::begin(_currentItemWords),
|
||||
std::end(_currentItemWords),
|
||||
ch,
|
||||
[](utf16string word, utf16char ch) { return word[0] < ch; });
|
||||
auto end = std::upper_bound(
|
||||
std::begin(_currentItemWords),
|
||||
std::end(_currentItemWords),
|
||||
ch,
|
||||
[](utf16char ch, utf16string word) { return ch < word[0]; });
|
||||
return _currentItemWords.subspan(
|
||||
begin - _currentItemWords.begin(),
|
||||
end - begin);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
'<(src_loc)',
|
||||
'<(submodules_loc)/GSL/include',
|
||||
'<(submodules_loc)/variant/include',
|
||||
'<(submodules_loc)/Catch/include'
|
||||
'<(submodules_loc)/Catch/include',
|
||||
'<(libs_loc)/range-v3/include',
|
||||
],
|
||||
'sources': [
|
||||
'<(src_loc)/base/tests_main.cpp',
|
||||
|
|
Loading…
Add table
Reference in a new issue