VCCC  2024.05
VisualCamp Common C++ library
movable_box.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2024/01/02.
3 //
4 
5 #ifndef VCCC_RANGES_MOVABLE_BOX_HPP
6 #define VCCC_RANGES_MOVABLE_BOX_HPP
7 
8 #include <initializer_list>
9 #include <type_traits>
10 #include <utility>
11 
16 #include "vccc/optional.hpp"
21 
22 namespace vccc {
23 namespace detail {
24 
25 template<typename T>
26 struct movable_box_store_obj_only
27  : disjunction<
28  copyable<T>,
29  conjunction<
30  copy_constructible<T>,
31  std::is_nothrow_move_constructible<T>,
32  std::is_nothrow_copy_constructible<T> >,
33  conjunction<
34  negation< copy_constructible<T> >,
35  movable<T> >,
36  conjunction<
37  negation< copy_constructible<T> >,
38  std::is_nothrow_copy_constructible<T> >
39  > {};
40 
42 struct movable_box_storage_base;
43 
44 template<typename T>
45 struct movable_box_storage_base<T, true> {
46 
47  constexpr movable_box_storage_base() = default;
48  constexpr movable_box_storage_base(const movable_box_storage_base&) = default;
49  constexpr movable_box_storage_base(movable_box_storage_base&&) = default;
50  constexpr movable_box_storage_base& operator=(const movable_box_storage_base&) = default;
51  constexpr movable_box_storage_base& operator=(movable_box_storage_base&&) = default;
52 
53  template<typename InPlace, std::enable_if_t<conjunction<
54  std::is_same<in_place_t, InPlace>,
55  std::is_constructible<T>
56  >::value, int> = 0>
57  constexpr movable_box_storage_base(InPlace)
59  : value_() {}
60 
61  template<typename U, std::enable_if_t<conjunction<
62  negation< std::is_same<in_place_t, remove_cvref_t<U>> >,
63  negation< std::is_same<movable_box_storage_base, remove_cvref_t<U>> >,
64  std::is_constructible<T, U>
65  >::value, int> = 0>
66  constexpr movable_box_storage_base(U&& arg)
68  : value_(std::forward<U>(arg)) {}
69 
70  template<typename Arg, typename... Args, std::enable_if_t<conjunction<
71  std::is_constructible<T, Arg, Args...>
72  >::value, int> = 0>
73  constexpr movable_box_storage_base(in_place_t, Arg&& arg, Args&&... args)
75  : value_(std::forward<Arg>(arg), std::forward<Args>(args)...) {}
76 
77  template<typename U, typename... Args, std::enable_if_t<conjunction<
78  std::is_constructible<T, std::initializer_list<U>, Args...>
79  >::value, int> = 0>
80  constexpr movable_box_storage_base(in_place_t, std::initializer_list<U> il, Args&&... args)
81  noexcept(std::is_nothrow_constructible<T, std::initializer_list<U>, Args...>::value)
82  : value_(il, std::forward<Args>(args)...) {}
83 
84  template<typename U, std::enable_if_t<conjunction<
85  negation< std::is_same<movable_box_storage_base, std::decay_t<U>> >,
86  std::is_assignable<T, U>
87  >::value, int> = 0>
88  constexpr movable_box_storage_base& operator=(U&& arg) noexcept(std::is_nothrow_assignable<T, U>::value) {
89  value_ = std::forward<U>(arg);
90  return *this;
91  }
92 
93  constexpr explicit operator bool() const noexcept { return true; }
94  constexpr bool has_value() const noexcept { return true; }
95 
96  constexpr const T* operator->() const noexcept { return vccc::addressof(value_); }
97  constexpr T* operator->() noexcept { return vccc::addressof(value_); }
98  constexpr const T& operator*() const& noexcept { return value_; }
99  constexpr T& operator*() & noexcept { return value_; }
100  constexpr const T&& operator*() const&& noexcept { return std::move(value_); }
101  constexpr T&& operator*() && noexcept { return std::move(value_); }
102 
103  constexpr void reset() noexcept { value_.~T(); }
104 
105  template<typename... Args, std::enable_if_t<std::is_constructible<T, Args...>::value, int> = 0>
106  constexpr T& emplace(Args&&... args)
107  noexcept(conjunction< std::is_nothrow_constructible<T, Args...>,
108  std::is_nothrow_destructible<T> >::value)
109  {
110  value_.~T();
111  ::new(this->operator->()) T(std::forward<Args>(args)...);
112  return value_;
113  }
114 
115  template<typename U, typename... Args, std::enable_if_t<std::is_constructible<T, std::initializer_list<U>, Args...>::value, int> = 0>
116  constexpr T& emplace(std::initializer_list<U> il, Args&&... args)
117  noexcept(conjunction< std::is_nothrow_constructible<T, std::initializer_list<U>, Args...>,
118  std::is_nothrow_destructible<T> >::value)
119  {
120  value_.~T();
121  ::new(this->operator->()) T(il, std::forward<Args>(args)...);
122  return value_;
123  }
124 
125  private:
126  T value_;
127 };
128 
129 template<typename T>
130 struct movable_box_storage_base<T, false> : private optional<T> {
131  using base = optional<T>;
132 
133  using base::base;
134  using base::operator=;
135  using base::operator->;
136  using base::operator*;
137  using base::operator bool;
138  using base::has_value;
139  using base::reset;
140  using base::emplace;
141 };
142 
143 template<typename T, bool = conjunction<copyable<T>, copy_constructible<T>>::value /* true */>
144 struct movable_box_storage_copy_assign : movable_box_storage_base<T> {
145  using base = movable_box_storage_base<T>;
146  using base::base;
147 };
148 
149 template<typename T>
150 struct movable_box_storage_copy_assign<T, false> : movable_box_storage_base<T> {
151  using base = movable_box_storage_base<T>;
152  using base::base;
153 
154  constexpr movable_box_storage_copy_assign() = default;
155  constexpr movable_box_storage_copy_assign(const movable_box_storage_copy_assign&) = default;
156  constexpr movable_box_storage_copy_assign(movable_box_storage_copy_assign&&) = default;
157 
158  movable_box_storage_copy_assign& operator=(const movable_box_storage_copy_assign& other)
160  {
161  if (this != vccc::addressof(other)) {
162  if (other)
163  this->emplace(*other);
164  else
165  this->reset();
166  }
167  return *this;
168  }
169  constexpr movable_box_storage_copy_assign& operator=(movable_box_storage_copy_assign&&) = default;
170 };
171 
173 struct movable_box_storage_move_assign : movable_box_storage_copy_assign<T> {
174  using base = movable_box_storage_copy_assign<T>;
175  using base::base;
176 
177  constexpr movable_box_storage_move_assign() = default;
178  constexpr movable_box_storage_move_assign(const movable_box_storage_move_assign&) = default;
179  constexpr movable_box_storage_move_assign(movable_box_storage_move_assign&&) = default;
180  constexpr movable_box_storage_move_assign& operator=(const movable_box_storage_move_assign&) = default;
181  constexpr movable_box_storage_move_assign& operator=(movable_box_storage_move_assign&& other) = default;
182 };
183 
184 template<typename T>
185 struct movable_box_storage_move_assign<T, false> : movable_box_storage_copy_assign<T> {
186  using base = movable_box_storage_copy_assign<T>;
187  using base::base;
188 
189  constexpr movable_box_storage_move_assign() = default;
190  constexpr movable_box_storage_move_assign(const movable_box_storage_move_assign&) = default;
191  constexpr movable_box_storage_move_assign(movable_box_storage_move_assign&&) = default;
192  constexpr movable_box_storage_move_assign& operator=(const movable_box_storage_move_assign&) = default;
193  constexpr movable_box_storage_move_assign& operator=(movable_box_storage_move_assign&& other)
195  {
196  if (this != vccc::addressof(other)) {
197  if (other)
198  this->emplace(std::move(*other));
199  else
200  this->reset();
201  }
202  return *this;
203  }
204 };
205 
206 } // namespace detail
207 
210 
211 template<typename T>
212 class movable_box : public detail::movable_box_storage_move_assign<T> {
213  using base = detail::movable_box_storage_move_assign<T>;
214  using base::base;
215 
216  public:
217  static_assert(move_constructible<T>::value, "Constraints not satisfied");
218  static_assert(std::is_object<T>::value, "Constraints not satisfied");
219 
220  constexpr movable_box() = default;
221  constexpr movable_box(const movable_box&) = default;
222  constexpr movable_box(movable_box&&) = default;
223  constexpr movable_box& operator=(const movable_box&) = default;
224  constexpr movable_box& operator=(movable_box&&) = default;
225 };
226 
228 
229 } // namespace vccc
230 
231 #endif // VCCC_RANGES_MOVABLE_BOX_HPP
Definition: movable_box.hpp:212
constexpr movable_box(const movable_box &)=default
constexpr movable_box()=default
constexpr movable_box(movable_box &&)=default
constexpr movable_box & operator=(movable_box &&)=default
constexpr movable_box & operator=(const movable_box &)=default
constexpr MatrixMulMatrix< E1, E2 > operator*(const MatrixBase< E1 > &lhs, const MatrixBase< E2 > &rhs)
Definition: matrix_mul_matrix.hpp:77
std::enable_if_t< std::is_object< T >::value, T * > addressof(T &t) noexcept
Definition: addressof.hpp:33
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35