kblib 0.2.3
General utilities library for modern C++
simple.h
Go to the documentation of this file.
1/* *****************************************************************************
2 * kblib is a general utility library for C++14 and C++17, intended to provide
3 * performant high-level abstractions and more expressive ways to do simple
4 * things.
5 *
6 * Copyright (c) 2021 killerbee
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * ****************************************************************************/
21
32#ifndef KBLIB_SIMPLE_H
33#define KBLIB_SIMPLE_H
34
35#include "iterators.h"
36
37#include <bitset>
38#include <climits>
39#include <cstdint>
40#include <initializer_list>
41#include <limits>
42#include <numeric>
43#include <utility>
44
45#define KBLIB_DEBUG_LOG_RANGES 0
46#if KBLIB_DEBUG_LOG_RANGES
47# include <iostream>
48#endif
49
50namespace KBLIB_NS {
51
52namespace detail_simple {
53 template <typename T>
54 struct simple_range {
55 const T& low;
56 const T& high;
57 };
58} // namespace detail_simple
59
60template <typename T>
61constexpr auto in_range(const T& v, detail_simple::simple_range<T> r) {
62 return (r.low <= v) and (v < r.high);
63}
64template <typename T>
65constexpr auto in_range_i(const T& v, detail_simple::simple_range<T> r) {
66 return (r.low <= v) and (v <= r.high);
67}
68
69#if KBLIB_USE_CXX17
70
71template <typename... Ts>
72constexpr bool any_void = (std::is_void_v<Ts> or ...);
73
74template <typename F, typename... T>
75KBLIB_NODISCARD auto map(F f, T&&... t) noexcept(noexcept(std::tuple{
76 kblib::apply(f, std::forward<T>(t))...}))
77 -> enable_if_t<
78 not any_void<decltype(kblib::apply(f, std::forward<T>(t)))...>,
79 decltype(std::tuple{kblib::apply(f, std::forward<T>(t))...})> {
80 return std::tuple{kblib::apply(f, std::forward<T>(t))...};
81}
82
83template <typename F, typename... T>
84auto map(F f, T&&... t) noexcept(
85 noexcept((static_cast<void>(kblib::apply(f, std::forward<T>(t))), ...)))
86 -> enable_if_t<any_void<decltype(kblib::apply(f, std::forward<T>(t)))...>,
87 void> {
88 (static_cast<void>(kblib::apply(f, std::forward<T>(t))), ...);
89}
90#endif
91
92template <typename T>
94 T t;
95 ~RAII_wrapper() noexcept(noexcept(t())) { t(); }
96
98 : t(std::move(t_)) {}
99 RAII_wrapper(const T& t_)
100 : t(t_) {}
101 RAII_wrapper(const RAII_wrapper&) = delete;
105};
106
107template <typename F>
108auto defer(F f) {
109 return RAII_wrapper<F>{std::move(f)};
110}
111
121template <typename BinaryOperation>
122KBLIB_NODISCARD constexpr auto flip() -> auto {
123 return [](auto&& a, auto&& b) {
124 return BinaryOperation{}(static_cast<decltype(b)>(b),
125 static_cast<decltype(a)>(a));
126 };
127}
128
137template <typename BinaryOperation>
138KBLIB_NODISCARD constexpr auto flip(BinaryOperation op) -> auto {
139 return [op = std::move(op)](auto&& a, auto&& b) {
140 return op(static_cast<decltype(b)>(b), static_cast<decltype(a)>(a));
141 };
142}
143
144template <typename T, std::size_t N>
145KBLIB_NODISCARD constexpr auto is_consecutive(const T (&array)[N])
147 if (N <= 1) {
148 return true;
149 } else if (N == 2) {
150 return (array[1] - array[0]) == 1;
151 } else {
152 for (std::size_t i = 1; i < N; ++i) {
153 if ((array[i] - array[i - 1]) != 1) {
154 return false;
155 }
156 }
157 return true;
158 }
159}
160
166KBLIB_NODISCARD constexpr auto filg2(
167 const std::bitset<std::numeric_limits<std::uintmax_t>::digits> val) noexcept
168 -> int {
169 for (auto i : range<int>(to_signed(val.size()) - 1, 0, -1)) {
170 if (val[to_unsigned(i)])
171 return i;
172 }
173 return 0;
174}
175
176template <std::size_t size, typename T, typename... Ts>
178 : std::conditional<sizeof(T) >= size, detail::tag<T>,
179 typename first_bigger_than<size, Ts...>::type> {};
180
181template <std::size_t size, typename T>
183 : std::conditional_t<sizeof(T) >= size, detail::tag<T>, void> {};
184
185template <std::uintmax_t I>
187 typename first_bigger_than<1 + filg2(I) / CHAR_BIT, unsigned char,
188 unsigned short, unsigned int, unsigned long,
189 unsigned long long, std::uintmax_t>::type;
190
191template <std::uintmax_t I>
193 typename first_bigger_than<1 + (filg2(I) + 1) / CHAR_BIT, signed char,
194 signed short, signed int, signed long,
195 signed long long, std::uintmax_t>::type;
196
197template <std::uintmax_t I>
199
200template <std::uintmax_t I>
202
206struct identity {
207 template <typename T>
208 KBLIB_NODISCARD auto operator()(T&& in) -> T&& {
209 return static_cast<T&&>(in);
210 }
211};
212
216template <typename T>
217auto safe_auto(T&& in) -> T {
218 return std::forward<T>(in);
219}
220
224template <typename T>
225auto safe_auto(T& in) -> T& {
226 return in;
227}
228
236template <typename LeftContainer, typename RightContainer>
237auto arraycat(LeftContainer A, RightContainer&& B) noexcept(
238 noexcept(A.insert(A.end(), B.begin(), B.end()))
239 and std::is_nothrow_move_constructible<LeftContainer>::value)
240 -> LeftContainer {
241 A.insert(A.end(), B.begin(), B.end());
242 return std::move(A);
243}
244
254template <typename T>
255KBLIB_NODISCARD constexpr auto a(const std::initializer_list<T>& a) -> auto {
256 return a.begin();
257}
258// use like:
259// auto v = a({2, 3, 5, 7, 9, 11})[2];
260
261#if KBLIB_USE_CXX20
262
263template <typename T>
264concept zero_constructible = requires(T t) {
265 {t = 0};
266};
267
268struct zero_t {
269 consteval zero_t(int i) { i == 0 ? void() : throw 0; }
270 template <zero_constructible T>
271 constexpr operator T() const noexcept {
272 return 0;
273 }
274 explicit constexpr operator std::nullptr_t() const noexcept {
275 return nullptr;
276 }
277};
278
279#endif
280
281} // namespace KBLIB_NS
282
283#undef KBLIB_DEBUG_LOG_RANGES
284
285#endif // KBLIB_SIMPLE_H
This file provides some iterators, ranges, iterator/range adapters, and operations that can be perfor...
constexpr auto size(const C &c) -> decltype(c.size())
Definition: fakestd.h:366
typename first_bigger_than< 1+(filg2(I)+1)/CHAR_BIT, signed char, signed short, signed int, signed long, signed long long, std::uintmax_t >::type int_smallest
Definition: simple.h:195
constexpr auto in_range(const T &v, detail_simple::simple_range< T > r)
Definition: simple.h:61
constexpr auto is_consecutive(const T(&array)[N]) -> enable_if_t< std::is_integral< T >::value, bool >
Definition: simple.h:145
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))...})>
Definition: simple.h:75
constexpr auto to_signed(I x) -> std::make_signed_t< I >
Cast integral argument to corresponding signed type.
Definition: fakestd.h:593
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:255
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:54
constexpr auto apply(F &&f, Arg &&arg) noexcept(noexcept(detail::apply_impl< F, Arg >::do_apply(std::forward< F >(f), std::forward< Arg >(arg), std::index_sequence< std::tuple_size< Arg >::value >{}))) -> decltype(auto)
Definition: fakestd.h:562
auto arraycat(LeftContainer A, RightContainer &&B) noexcept(noexcept(A.insert(A.end(), B.begin(), B.end())) and std::is_nothrow_move_constructible< LeftContainer >::value) -> LeftContainer
Concatenate two dynamic containers together.
Definition: simple.h:237
typename int_smallest< I >::type int_smallest_t
Definition: simple.h:201
constexpr auto filg2(const std::bitset< std::numeric_limits< std::uintmax_t >::digits > val) noexcept -> int
Floored integer binary logarithm. Returns floor(lb(val)).
Definition: simple.h:166
auto safe_auto(T &in) -> T &
Safely propagate an xvalue or lvalue without dangling references.
Definition: simple.h:225
auto defer(F f)
Definition: simple.h:108
constexpr auto flip(BinaryOperation op) -> auto
Transforms a binary operation into one which takes reversed arguments.
Definition: simple.h:138
constexpr bool any_void
Definition: simple.h:72
typename first_bigger_than< 1+filg2(I)/CHAR_BIT, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, std::uintmax_t >::type uint_smallest
Definition: simple.h:189
typename uint_smallest< I >::type uint_smallest_t
Definition: simple.h:198
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
Definition: fakestd.h:586
constexpr auto in_range_i(const T &v, detail_simple::simple_range< T > r)
Definition: simple.h:65
Definition: bits.h:721
RAII_wrapper(T &&t_)
Definition: simple.h:97
RAII_wrapper(const RAII_wrapper &)=delete
RAII_wrapper & operator=(const RAII_wrapper &)=delete
RAII_wrapper(const T &t_)
Definition: simple.h:99
RAII_wrapper(RAII_wrapper &&)=delete
~RAII_wrapper() noexcept(noexcept(t()))
Definition: simple.h:95
RAII_wrapper & operator=(RAII_wrapper &&)=delete
The identity function, as a function object.
Definition: simple.h:206
auto operator()(T &&in) -> T &&
Definition: simple.h:208
#define KBLIB_NS
Definition: tdecl.h:113
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129