SeqAn3 3.3.0-rc.1
The Modern C++ library for sequence analysis.
copyable_wrapper.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2022, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6// -----------------------------------------------------------------------------------------------------
7
13#pragma once
14
15#include <functional>
16#include <optional>
17
19
20namespace seqan3::detail
21{
22
28template <typename t>
29concept boxable = std::copy_constructible<t> && std::is_object_v<t>;
30
35template <typename t>
37{
38public:
40 using std::optional<t>::operator=;
41 constexpr copyable_wrapper(copyable_wrapper const &) = default;
42 constexpr copyable_wrapper(copyable_wrapper &&) = default;
43 constexpr ~copyable_wrapper() = default;
44
48 constexpr copyable_wrapper() noexcept(std::is_nothrow_default_constructible_v<t>)
49 requires std::default_initializable<t>
51 {}
52
54 constexpr copyable_wrapper &
55 operator=(copyable_wrapper const & other) noexcept(std::is_nothrow_copy_constructible_v<t>)
56 requires (!std::copyable<t>)
57 {
58 if (this != std::addressof(other))
59 {
60 if (other)
61 this->emplace(*other);
62 else
63 this->reset();
64 }
65 return *this;
66 }
67
69 constexpr copyable_wrapper & operator=(copyable_wrapper && other) noexcept(std::is_nothrow_move_constructible_v<t>)
70 requires (!std::movable<t>)
71 {
72 if (this != std::addressof(other))
73 {
74 if (other)
75 this->emplace(std::move(*other));
76 else
77 this->reset();
78 }
79 return *this;
80 }
81
93 template <typename... args_t>
94 requires std::invocable<t, args_t...>
95 constexpr decltype(auto) operator()(args_t... args) noexcept(std::is_nothrow_invocable_v<t, args_t...>)
96 {
97 return std::invoke(this->value(), std::forward<args_t>(args)...);
98 }
99
101 template <typename... args_t>
102 requires std::invocable<t, args_t...>
103 constexpr decltype(auto) operator()(args_t... args) const noexcept(std::is_nothrow_invocable_v<t, args_t...>)
104 {
105 return std::invoke(this->value(), std::forward<args_t>(args)...);
106 }
107};
108
116template <boxable t>
117 requires std::copyable<t>
118 || (std::is_nothrow_move_constructible_v<t> && std::is_nothrow_copy_constructible_v<t>)
119#if SEQAN3_WORKAROUND_DEFAULT_CONSTRUCTIBLE_VIEW // If views must be default constructible, t must also be
120 && std::default_initializable<t>
121#endif
123{
124private:
125 t value{};
126
127public:
130 requires std::default_initializable<t>
131 = default;
132
133 constexpr copyable_wrapper(copyable_wrapper const &) = default;
134 constexpr copyable_wrapper(copyable_wrapper &&) = default;
135 constexpr ~copyable_wrapper() = default;
136
138 constexpr copyable_wrapper & operator=(copyable_wrapper const &)
139 requires std::copyable<t>
140 = default;
141
143 constexpr copyable_wrapper & operator=(copyable_wrapper const & other) noexcept
144 {
145 // Destroy-then-copy
146 if (this != std::addressof(other))
147 {
148 value.~t(); // Call destructor of value
149 std::construct_at(std::addressof(value), *other); // Copy construct
150 }
151 return *this;
152 }
153
156 requires std::copyable<t>
157 = default;
158
160 constexpr copyable_wrapper & operator=(copyable_wrapper && other) noexcept
161 {
162 // Destroy-then-copy
163 if (this != std::addressof(other))
164 {
165 value.~t(); // Call destructor of value
166 std::construct_at(std::addressof(value), std::move(*other)); // Move construct
167 }
168 return *this;
169 }
170
172 constexpr explicit copyable_wrapper(t const & other) noexcept(std::is_nothrow_copy_constructible_v<t>) :
173 value{other}
174 {}
175
177 constexpr explicit copyable_wrapper(t && other) noexcept(std::is_nothrow_move_constructible_v<t>) :
178 value{std::move(other)}
179 {}
180
182 template <typename... args_t>
183 requires std::constructible_from<t, args_t...>
185 args_t... args) noexcept(std::is_nothrow_constructible_v<t, args_t...>) :
186 value{std::forward<args_t>(args)...}
187 {}
188
190 constexpr bool has_value() const noexcept
191 {
192 return true; // t is copyable, hence we always store a value.
193 }
194
196 constexpr t & operator*() noexcept
197 {
198 return value;
199 }
200
202 constexpr t const & operator*() const noexcept
203 {
204 return value;
205 }
206
208 constexpr t * operator->() noexcept
209 {
210 return std::addressof(value);
211 }
212
214 constexpr t const * operator->() const noexcept
215 {
216 return std::addressof(value);
217 }
218
229 template <typename... args_t>
230 requires std::invocable<t, args_t...>
231 constexpr decltype(auto) operator()(args_t... args) noexcept(std::is_nothrow_invocable_v<t, args_t...>)
232 {
233 return std::invoke(value, std::forward<args_t>(args)...);
234 }
235
237 template <typename... args_t>
238 requires std::invocable<t, args_t...>
239 constexpr decltype(auto) operator()(args_t... args) const noexcept(std::is_nothrow_invocable_v<t, args_t...>)
240 {
241 return std::invoke(value, std::forward<args_t>(args)...);
242 }
243};
244
248template <typename t>
250
256template <typename t>
258
259} // namespace seqan3::detail
T addressof(T... args)
Utility wrapper that behaves like std::optional but makes the type conform with the std::copyable con...
Definition: copyable_wrapper.hpp:123
constexpr copyable_wrapper(t &&other) noexcept(std::is_nothrow_move_constructible_v< t >)
Move construct from value.
Definition: copyable_wrapper.hpp:177
constexpr t & operator*() noexcept
Returns a reference to the wrapped object. Part of the std::optional API.
Definition: copyable_wrapper.hpp:196
constexpr copyable_wrapper(std::in_place_t, args_t... args) noexcept(std::is_nothrow_constructible_v< t, args_t... >)
Construct from argument pack. Part of the std::optional API.
Definition: copyable_wrapper.hpp:184
constexpr copyable_wrapper(t const &other) noexcept(std::is_nothrow_copy_constructible_v< t >)
Copy construct from value.
Definition: copyable_wrapper.hpp:172
constexpr t const & operator*() const noexcept
Returns a reference to the wrapped object. Part of the std::optional API.
Definition: copyable_wrapper.hpp:202
constexpr t * operator->() noexcept
Returns a pointer to the wrapped object. Part of the std::optional API.
Definition: copyable_wrapper.hpp:208
constexpr bool has_value() const noexcept
Return whether the wrapper contains a value. Part of the std::optional API.
Definition: copyable_wrapper.hpp:190
constexpr t const * operator->() const noexcept
Returns a pointer to the wrapped object. Part of the std::optional API.
Definition: copyable_wrapper.hpp:214
constexpr copyable_wrapper & operator=(copyable_wrapper &&)=default
Move assignment for copyable types is the default move assignment.
constexpr copyable_wrapper()=default
copyable_wrapper is default constructible, iff the wrapped type is default initialisable.
Utility wrapper that behaves like std::optional but makes the type conform with the std::copyable con...
Definition: copyable_wrapper.hpp:37
constexpr ~copyable_wrapper()=default
Defaulted.
constexpr copyable_wrapper(copyable_wrapper &&)=default
Defaulted.
constexpr copyable_wrapper & operator=(copyable_wrapper const &other) noexcept(std::is_nothrow_copy_constructible_v< t >)
Copy assignment for non-copyable wrapped types.
Definition: copyable_wrapper.hpp:55
constexpr copyable_wrapper() noexcept(std::is_nothrow_default_constructible_v< t >)
Use a specialised default constructor, if the wrapped type is default initialisable....
Definition: copyable_wrapper.hpp:48
constexpr copyable_wrapper & operator=(copyable_wrapper &&other) noexcept(std::is_nothrow_move_constructible_v< t >)
Move assignment for non-movable wrapped types.
Definition: copyable_wrapper.hpp:69
copyable_wrapper(t) -> copyable_wrapper< std::remove_reference_t< t > >
Type deduction guide that strips references.
constexpr copyable_wrapper(copyable_wrapper const &)=default
< Use std::optional assignment operators.
Helper concept for seqan3::detail::copyable_wrapper.
Definition: copyable_wrapper.hpp:29
T construct_at(T... args)
T emplace(T... args)
T in_place
T invoke(T... args)
T is_nothrow_constructible_v
The internal SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
SeqAn specific customisations in the standard namespace.
Provides platform and dependency checks.
#define SEQAN3_WORKAROUND_DEFAULT_CONSTRUCTIBLE_VIEW
A view does not need to be default constructible. This change is first implemented in gcc12.
Definition: platform.hpp:235
T reset(T... args)
T value(T... args)