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 constexpr 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>
84constexpr auto 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 constexpr ~RAII_wrapper() noexcept(noexcept(t())) { t(); }
96
97 constexpr RAII_wrapper(T&& t_)
98 : t(std::move(t_)) {}
99 constexpr RAII_wrapper(const T& t_)
100 : t(t_) {}
101 constexpr RAII_wrapper(const RAII_wrapper&) = delete;
102 constexpr RAII_wrapper(RAII_wrapper&&) = delete;
103 constexpr RAII_wrapper& operator=(const RAII_wrapper&) = delete;
104 constexpr RAII_wrapper& operator=(RAII_wrapper&&) = delete;
105};
106
107template <typename F>
108constexpr auto 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 }
174 return 0;
175}
176
177template <std::size_t size, typename T, typename... Ts>
179 : std::conditional<sizeof(T) >= size, detail::tag<T>,
180 typename first_bigger_than<size, Ts...>::type> {};
181
182template <std::size_t size, typename T>
184 : std::conditional_t<sizeof(T) >= size, detail::tag<T>, void> {};
185
186template <std::uintmax_t I>
188 typename first_bigger_than<1 + filg2(I) / CHAR_BIT, unsigned char,
189 unsigned short, unsigned int, unsigned long,
190 unsigned long long, std::uintmax_t>::type;
191
192template <std::uintmax_t I>
194 typename first_bigger_than<1 + (filg2(I) + 1) / CHAR_BIT, signed char,
195 signed short, signed int, signed long,
196 signed long long, std::uintmax_t>::type;
197
198template <std::uintmax_t I>
200
201template <std::uintmax_t I>
203
207struct identity {
208 template <typename T>
209 KBLIB_NODISCARD constexpr auto operator()(T&& in) -> T&& {
210 return static_cast<T&&>(in);
211 }
212};
213
217template <typename T>
218constexpr auto safe_auto(T&& in) -> T {
219 return std::forward<T>(in);
220}
221
225template <typename T>
226constexpr auto safe_auto(T& in) -> T& {
227 return in;
228}
229
237template <typename LeftContainer, typename RightContainer>
238constexpr auto arraycat(LeftContainer A, RightContainer&& B) noexcept(
239 noexcept(A.insert(A.end(), B.begin(), B.end()))
241 -> LeftContainer {
242 A.insert(A.end(), B.begin(), B.end());
243 return std::move(A);
244}
245
255template <typename T>
256KBLIB_NODISCARD constexpr auto a(const std::initializer_list<T>& a) -> auto {
257 return a.begin();
258}
259// use like:
260// auto v = a({2, 3, 5, 7, 9, 11})[2];
261
262#if KBLIB_USE_CXX20
263
264template <typename T>
265concept zero_constructible = requires(T t) {
266 { t = 0 };
267};
268
269struct zero_t {
270 consteval zero_t(int i) { i == 0 ? void() : throw 0; }
271 template <zero_constructible T>
272 constexpr operator T() const noexcept {
273 return 0;
274 }
275 explicit constexpr operator std::nullptr_t() const noexcept {
276 return nullptr;
277 }
278};
279
280#endif
281
282} // namespace KBLIB_NS
283
284#undef KBLIB_DEBUG_LOG_RANGES
285
286#endif // KBLIB_SIMPLE_H
This file provides some iterators, ranges, iterator/range adapters, and operations that can be perfor...
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:4001
constexpr auto size(const C &c) -> decltype(c.size())
Definition: fakestd.h:383
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:196
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
constexpr auto to_signed(I x) -> std::make_signed_t< I >
Cast integral argument to corresponding signed type.
Definition: fakestd.h:609
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:256
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:62
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:579
typename int_smallest< I >::type int_smallest_t
Definition: simple.h:202
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
constexpr 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:238
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
constexpr auto safe_auto(T &in) -> T &
Safely propagate an xvalue or lvalue without dangling references.
Definition: simple.h:226
constexpr 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 defer(F f)
Definition: simple.h:108
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:190
typename uint_smallest< I >::type uint_smallest_t
Definition: simple.h:199
constexpr auto to_unsigned(I x) -> std::make_unsigned_t< I >
Cast integral argument to corresponding unsigned type.
Definition: fakestd.h:602
constexpr auto in_range_i(const T &v, detail_simple::simple_range< T > r)
Definition: simple.h:65
Definition: bits.h:719
constexpr RAII_wrapper(RAII_wrapper &&)=delete
constexpr ~RAII_wrapper() noexcept(noexcept(t()))
Definition: simple.h:95
constexpr RAII_wrapper(const T &t_)
Definition: simple.h:99
constexpr RAII_wrapper(T &&t_)
Definition: simple.h:97
constexpr RAII_wrapper & operator=(RAII_wrapper &&)=delete
constexpr RAII_wrapper & operator=(const RAII_wrapper &)=delete
constexpr RAII_wrapper(const RAII_wrapper &)=delete
The identity function, as a function object.
Definition: simple.h:207
constexpr auto operator()(T &&in) -> T &&
Definition: simple.h:209
#define KBLIB_NS
Definition: tdecl.h:130
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:146