kblib 0.2.3
General utilities library for modern C++
delayed_construct.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 DELAYED_CONSTRUCT_H
33#define DELAYED_CONSTRUCT_H
34
35#include "hash.h"
36#include "tdecl.h"
37
38#if KBLIB_USE_CXX17
39
40# include <optional>
41
42namespace kblib {
43
44template <typename T>
45class delayed_construct : protected std::optional<T> {
46 private:
47 using Base = std::optional<T>;
48
49 public:
50 using Base::Base;
51
52 template <typename U,
53 std::enable_if_t<std::is_assignable_v<T&, U&&>, int> = 0>
54 auto operator=(U&& t) -> delayed_construct& {
55 Base::operator=(std::forward<U>(t));
56 return *this;
57 }
58
59 using Base::operator->;
60 using Base::operator*;
61
62 using Base::operator bool;
63 KBLIB_NODISCARD constexpr auto is_constructed() const noexcept -> bool {
64 return Base::has_value();
65 }
66
67 using Base::value;
68
69 using Base::emplace;
70
71 // TODO(killerbee13): add C++20 operator<=> support to delayed_construct
72
73# if 0 && KBLIB_USE_CXX20
74
75 KBLIB_NODISCARD auto operator<=>(const delayed_construct& lhs,
76 const delayed_construct& rhs) = default;
77 KBLIB_NODISCARD auto operator<=>(const delayed_construct& lhs, std::nullopt_t rhs);
78 KBLIB_NODISCARD auto operator<=>(const delayed_construct& lhs, const U& rhs);
79
80# else
81
82# define OVERLOAD_DEFER_OP(op) \
83 KBLIB_NODISCARD friend constexpr auto operator op( \
84 const delayed_construct& lhs, \
85 const delayed_construct& rhs) noexcept->bool { \
86 return static_cast<const Base&>(lhs) \
87 op static_cast<const Base&>(rhs); \
88 } \
89 template <typename U> \
90 KBLIB_NODISCARD friend constexpr auto operator op( \
91 const delayed_construct& lhs, \
92 const delayed_construct<U>& rhs) noexcept->bool { \
93 return static_cast<const Base&>(lhs) \
94 op static_cast<const std::optional<U>&>(rhs); \
95 } \
96 KBLIB_NODISCARD friend constexpr auto operator op( \
97 const delayed_construct& lhs, \
98 std::nullopt_t rhs) noexcept->bool { \
99 return static_cast<const Base&>(lhs) op rhs; \
100 } \
101 KBLIB_NODISCARD friend constexpr auto operator op( \
102 std::nullopt_t lhs, \
103 const delayed_construct& rhs) noexcept->bool { \
104 return lhs op static_cast<const Base&>(rhs); \
105 } \
106 template <typename U> \
107 KBLIB_NODISCARD friend constexpr auto operator op( \
108 const delayed_construct& opt, const U& value) noexcept->bool { \
109 return static_cast<const Base&>(opt) op value; \
110 } \
111 template <typename U> \
112 KBLIB_NODISCARD friend constexpr auto operator op( \
113 const U& value, const delayed_construct& opt) noexcept->bool { \
114 return value op static_cast<const Base&>(opt); \
115 }
116
128
141
142# undef OVERLOAD_DEFER_OP
143# endif
144
145 friend struct std::hash<delayed_construct<T>>;
146 friend struct FNV_hash<delayed_construct<T>>;
147};
148
149template <typename T>
150struct FNV_hash<delayed_construct<T>, void> {
151 KBLIB_NODISCARD constexpr std::size_t operator()(
152 const delayed_construct<T>& key,
153 std::size_t offset
154 = fnv::fnv_offset<std::size_t>::value) const noexcept {
155 if (key) {
156 return FNV_hash<T>{}(key.value(), offset);
157 } else {
158 return FNV_hash<std::nullopt_t>{}(std::nullopt, offset);
159 }
160 }
161};
162
163} // namespace kblib
164
165namespace std {
166
167// Inheriting from another hash specialization means that this hash is (mostly)
168// disabled when std::hash<T> is (if I read the requirements correctly,
169// operator() should not be declared in a disabled std::hash, but I basically
170// can't do that in any sensible way)
171template <typename T>
172struct hash<kblib::delayed_construct<T>> : hash<T> {
174 auto operator()(const argument_type& value) const noexcept -> std::size_t {
175 return hash<optional<T>>{}(static_cast<const optional<T>&>(value));
176 }
177};
178
179} // namespace std
180
181#endif // KBLIB_USE_CXX17
182
183#endif // DELAYED_CONSTRUCT_H
auto operator=(U &&t) -> delayed_construct &
constexpr auto is_constructed() const noexcept -> bool
#define OVERLOAD_DEFER_OP(op)
Provides generic facilities for hashing data, and aliases for standard unordered containers using the...
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
Definition: bits.h:714
constexpr std::size_t operator()(const delayed_construct< T > &key, std::size_t offset=fnv::fnv_offset< std::size_t >::value) const noexcept
The primary template has to exist, but not be constructible, in order to be compatible with std::hash...
Definition: hash.h:334
The starting value for the FNVa hash algorithm, as a type trait.
Definition: hash.h:128
auto operator()(const argument_type &value) const noexcept -> std::size_t
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:81