31#ifndef KBLIB_CONTAINERS_H
32#define KBLIB_CONTAINERS_H
51 typename C::value_type ret = std::move(s.top());
56template <
class C,
typename K,
typename V>
58 ->
typename C::mapped_type {
59 auto it = m.find(key);
66template <
typename Map,
typename Key>
69 auto it =
map.find(std::forward<Key>(key));
76template <
typename iterator>
93template <
typename M,
typename K>
95 noexcept(m.find(key) != m.end())) ->
exists_t<
decltype(m.find(key))> {
96 auto it = m.find(key);
97 return {it, it != m.end()};
117 if (std::is_nothrow_move_constructible<typename V::value_type>::value) {
120 std::move(vec.begin(), vec.end(), std::back_inserter(tmp));
121 vec = std::move(tmp);
123 V tmp(vec.begin(), vec.end());
124 vec = std::move(tmp);
129template <
typename C, std::
size_t size>
134template <
typename C, std::
size_t size>
151template <
typename Container,
typename Range>
155 return Container{begin(std::forward<Range>(r)), end(std::forward<Range>(r))};
158template <
typename Container,
bool ArrayLike = not is_resizable_v<Container>>
169 std::shared_ptr<Container>
range;
178 template <
typename... Args>
180 :
range(
std::make_shared<Container>(
std::forward<Args>(args)...)) {}
183 std::is_nothrow_move_constructible<Container>::value) -> Container {
184 auto holder = std::move(
range);
185 return std::move(*holder);
189 std::is_nothrow_move_constructible<Container>::value) {
190 auto holder = std::move(
range);
191 return std::move(*holder);
203 noexcept(noexcept(*
std::back_inserter(*
range))) -> decltype(auto) {
204 return std::back_inserter(*
range);
222 template <
typename T>
224 noexcept(noexcept(T{std::declval<build_end_t&>()})) {
229template <
typename Container>
238 template <
typename... Args>
240 :
range(
std::make_shared<Container>(
std::forward<Args>(args)...)) {}
244 , index(
std::tuple_size<Container>::value) {}
247 std::is_nothrow_move_constructible<Container>::value) -> Container {
248 auto holder = std::move(
range);
249 return std::move(*holder);
253 std::is_nothrow_move_constructible<Container>::value) {
254 auto holder = std::move(
range);
255 return std::move(*holder);
259 return (*
range)[index];
262 return &(*range)[index];
287 return it.index == it.size();
291 return it.index != it.size();
296 return it.index == it.size();
300 return it.index != it.size();
306 return it1.index == it2.index;
311 return it1.index != it2.index;
323 std::shared_ptr<Container>
range;
330#if defined(__clang__)
332# pragma clang diagnostic push
333# pragma clang diagnostic ignored "-Wmismatched-tags"
336template <
typename C, std::
size_t Size>
338 :
public integral_constant<size_t, Size> {};
340#if defined(__clang__)
341# pragma clang diagnostic pop
348 template <
typename Container, std::
size_t N>
350 template <
typename T>
353 for (
auto& v : out) {
359 template <
typename T,
typename I>
360 constexpr static auto impl(T
value, I incr) -> Container {
362 for (
auto& v : out) {
372template <
typename T,
typename Container = std::vector<T>>
383 static_assert(std::is_same<T, value_type>::value,
384 "Container::value_type must be T.");
393 :
stack(Container()) {}
394 explicit stack(
const Container& cont)
397 template <
typename Alloc,
398 typename std::enable_if<
399 std::uses_allocator<container_type, Alloc>::value,
int>::type
402 template <
typename Alloc,
403 typename std::enable_if<
404 std::uses_allocator<container_type, Alloc>::value,
int>::type
406 stack(
const Container& cont,
const Alloc& alloc);
407 template <
typename Alloc,
408 typename std::enable_if<
409 std::uses_allocator<container_type, Alloc>::value,
int>::type
411 stack(Container && cont,
const Alloc& alloc);
412 template <
typename Alloc,
413 typename std::enable_if<
414 std::uses_allocator<container_type, Alloc>::value,
int>::type
417 template <
typename Alloc,
418 typename std::enable_if<
419 std::uses_allocator<container_type, Alloc>::value,
int>::type
426 return backing.back();
430 return backing.back();
437 return backing.size();
443 return backing.push_back(value);
446 return backing.push_back(std::move(value));
449 template <
typename... Args>
450 auto emplace(Args && ... args)&->decltype(
auto) {
451 return backing.emplace_back(std::forward<Args>(args)...);
454 auto pop() noexcept(noexcept(backing.pop_back()))->
void {
458 auto clear() noexcept(noexcept(backing.clear()))->
void {
467 swap(backing, other.backing);
477 return std::move(backing);
auto base() noexcept(std::is_nothrow_move_constructible< Container >::value) -> Container
auto operator++(int) -> build_iterator &
Advance to the next element.
constexpr friend auto operator!=(const build_iterator< Container > &it1, const build_iterator< Container > &it2) noexcept -> bool
build_iterator(Args &&... args)
auto operator*() const noexcept -> decltype(auto)
build_iterator(const build_end_t &)
constexpr auto size() const noexcept -> std::size_t
constexpr friend auto operator!=(const build_iterator< Container > &it, build_end_t) noexcept -> bool
constexpr friend auto operator==(build_end_t, const build_iterator< Container > &it) noexcept -> bool
auto operator++() -> build_iterator &
Advance to the next element.
constexpr friend auto operator==(const build_iterator< Container > &it, build_end_t) noexcept -> bool
constexpr friend auto operator==(const build_iterator< Container > &it1, const build_iterator< Container > &it2) noexcept -> bool
auto operator->() const noexcept -> auto *
constexpr friend auto operator!=(build_end_t, const build_iterator< Container > &it) noexcept -> bool
std::output_iterator_tag iterator_category
constexpr auto operator++(int) -> build_iterator &
A no-op.
build_iterator(Args &&... args)
constexpr auto base() noexcept(std::is_nothrow_move_constructible< Container >::value) -> Container
constexpr auto operator++() -> build_iterator &
A no-op.
constexpr auto operator*() const noexcept(noexcept(*std::back_inserter(*range))) -> decltype(auto)
Creates a temporary std::back_insert_iterator for the range and returns it.
std::output_iterator_tag iterator_category
auto push(value_type &&value) -> decltype(auto)
stack(Container &&cont, const Alloc &alloc)
stack(stack &&cont, const Alloc &alloc)
typename Container::reference reference
auto swap(stack &other) noexcept(fakestd::is_nothrow_swappable< Container >::value) -> void
stack(const stack &cont, const Alloc &alloc)
auto container() const &-> container_type &
auto top() &noexcept(noexcept(backing.back())) -> reference
auto clear() noexcept(noexcept(backing.clear())) -> void
auto pop() noexcept(noexcept(backing.pop_back())) -> void
typename Container::size_type size_type
stack(const Container &cont)
auto size() const noexcept -> size_type
auto container() &-> container_type &
typename Container::const_reference const_reference
auto container() &&-> container_type
auto top() const &noexcept(noexcept(backing.back())) -> const_reference
auto push(const value_type &value) -> decltype(auto)
auto empty() const noexcept -> bool
stack(const Alloc &alloc)
auto emplace(Args &&... args) &-> decltype(auto)
typename Container::value_type value_type
stack(const Container &cont, const Alloc &alloc)
This header provides some features of C++17 <type_traits> and other headers for C++14,...
This file provides some iterators, ranges, iterator/range adapters, and operations that can be perfor...
constexpr auto size(const C &c) -> decltype(c.size())
auto force_shrink_to_fit(V &vec) -> void
std::vector::shrink_to_fit is non-binding, which means that there is no guaranteed way to shrink a ve...
constexpr auto size(const C &c) -> decltype(c.size())
auto map(F f, T &&... t) noexcept(noexcept(std::tuple{ kblib::apply(f, std::forward< T >(t))...})) -> enable_if_t< not any_void< decltype(kblib::apply(f, std::forward< T >(t)))... >, decltype(std::tuple{kblib::apply(f, std::forward< T >(t))...})>
constexpr auto to_pointer(P &&p) noexcept -> auto *
Gets a raw pointer out of any smart pointer or iterator you might pass in, without dereferencing it o...
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
constexpr auto get_or(const C &m, const K &key, const V &defval) -> typename C::mapped_type
constexpr auto construct_from_range(Range &&r) -> Container
Allows for constructing a container of a specified type from a range object. Copy elision means that ...
auto try_reserve(C &c, std::size_t s) noexcept(noexcept(c.reserve(s))) -> void
Attempt to reserve capacity in a container. No-op if unsupported.
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
constexpr struct kblib::build_end_t build_end
constexpr auto try_get(Map &map, Key &&key) -> copy_const_t< Map, typename Map::mapped_type > *
constexpr auto pop(C &s) -> typename C::value_type
constexpr auto get_check(M &&m, const K &key) noexcept(noexcept(m.find(key) !=m.end())) -> exists_t< decltype(m.find(key))>
typename copy_const< C, V >::type copy_const_t
static constexpr auto make() -> C
static constexpr auto make() -> C
static constexpr auto impl(T value) -> Container
static constexpr auto impl(T value, I incr) -> Container
constexpr auto operator->() const noexcept -> iterator
constexpr auto addr() const noexcept -> auto *
constexpr auto operator*() const noexcept(noexcept(*it)) -> decltype(*it)
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_UNUSED
This internal macro is used to provide a fallback for [[maybe_unused]] in C++14.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Contains some type traits not in the standard library that are useful in the implementation of kblib.