lazy_init.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2023 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_DETAIL_LAZY_INIT_HPP_INCLUDED
5 #define LEXY_DETAIL_LAZY_INIT_HPP_INCLUDED
6 
9 
10 namespace lexy::_detail
11 {
12 template <typename T>
14 {
15  bool _init;
16  union
17  {
18  char _empty;
19  T _value;
20  };
21 
22  constexpr _lazy_init_storage_trivial() noexcept : _init(false), _empty() {}
23 
24  template <typename... Args>
25  constexpr _lazy_init_storage_trivial(int, Args&&... args)
26  : _init(true), _value(LEXY_FWD(args)...)
27  {}
28 };
29 
30 template <typename T>
32 {
33  bool _init;
34  union
35  {
36  char _empty;
37  T _value;
38  };
39 
40  constexpr _lazy_init_storage_non_trivial() noexcept : _init(false), _empty() {}
41 
42  template <typename... Args>
43  constexpr _lazy_init_storage_non_trivial(int, Args&&... args)
44  : _init(true), _value(LEXY_FWD(args)...)
45  {}
46 
48  {
49  if (_init)
50  _value.~T();
51  }
52 
54  : _init(other._init), _empty()
55  {
56  if (_init)
57  ::new (static_cast<void*>(&_value)) T(LEXY_MOV(other._value));
58  }
59 
61  {
62  if (_init && other._init)
63  _value = LEXY_MOV(other._value);
64  else if (_init && !other._init)
65  {
66  _value.~T();
67  _init = false;
68  }
69  else if (!_init && other._init)
70  {
71  ::new (static_cast<void*>(&_value)) T(LEXY_MOV(other._value));
72  _init = true;
73  }
74  else
75  {
76  // Both not initialized, nothing to do.
77  }
78 
79  return *this;
80  }
81 };
82 
83 template <typename T>
84 constexpr auto _lazy_init_trivial = [] {
85  // https://www.foonathan.net/2021/03/trivially-copyable/
86  return std::is_trivially_destructible_v<T> //
87  && std::is_trivially_copy_constructible_v<T> //
88  && std::is_trivially_copy_assignable_v<T> //
89  && std::is_trivially_move_constructible_v<T> //
90  && std::is_trivially_move_assignable_v<T>;
91 }();
92 template <typename T>
93 using _lazy_init_storage = std::conditional_t<_lazy_init_trivial<T>, _lazy_init_storage_trivial<T>,
95 
96 template <typename T>
98 {
99 public:
100  using value_type = T;
101 
102  constexpr lazy_init() noexcept = default;
103 
104  template <typename... Args>
105  constexpr T& emplace(Args&&... args)
106  {
107  LEXY_PRECONDITION(!*this);
108 
109  *this = lazy_init(0, LEXY_FWD(args)...);
110  return this->_value;
111  }
112 
113  template <typename Fn, typename... Args>
114  constexpr T& emplace_result(Fn&& fn, Args&&... args)
115  {
116  return emplace(LEXY_FWD(fn)(LEXY_FWD(args)...));
117  }
118 
119  constexpr explicit operator bool() const noexcept
120  {
121  return this->_init;
122  }
123 
124  constexpr T& operator*() & noexcept
125  {
126  LEXY_PRECONDITION(*this);
127  return this->_value;
128  }
129  constexpr const T& operator*() const& noexcept
130  {
131  LEXY_PRECONDITION(*this);
132  return this->_value;
133  }
134  constexpr T&& operator*() && noexcept
135  {
136  LEXY_PRECONDITION(*this);
137  return LEXY_MOV(this->_value);
138  }
139  constexpr const T&& operator*() const&& noexcept
140  {
141  LEXY_PRECONDITION(*this);
142  return LEXY_MOV(this->_value);
143  }
144 
145  constexpr T* operator->() noexcept
146  {
147  LEXY_PRECONDITION(*this);
148  return &this->_value;
149  }
150  constexpr const T* operator->() const noexcept
151  {
152  LEXY_PRECONDITION(*this);
153  return &this->_value;
154  }
155 
156 private:
157  template <typename... Args>
158  constexpr explicit lazy_init(int, Args&&... args) noexcept
159  : _lazy_init_storage<T>(0, LEXY_FWD(args)...)
160  {}
161 };
162 template <typename T>
163 class lazy_init<T&>
164 {
165 public:
166  using value_type = T&;
167 
168  constexpr lazy_init() noexcept : _ptr(nullptr) {}
169 
170  constexpr T& emplace(T& ref)
171  {
172  LEXY_PRECONDITION(!*this);
173  _ptr = &ref;
174  return ref;
175  }
176 
177  template <typename Fn, typename... Args>
178  constexpr T& emplace_result(Fn&& fn, Args&&... args)
179  {
180  return emplace(LEXY_FWD(fn)(LEXY_FWD(args)...));
181  }
182 
183  constexpr explicit operator bool() const noexcept
184  {
185  return _ptr != nullptr;
186  }
187 
188  constexpr T& operator*() const noexcept
189  {
190  LEXY_PRECONDITION(*this);
191  return *_ptr;
192  }
193 
194  constexpr T* operator->() const noexcept
195  {
196  LEXY_PRECONDITION(*this);
197  return _ptr;
198  }
199 
200 private:
201  T* _ptr;
202 };
203 template <>
205 {
206 public:
207  using value_type = void;
208 
209  constexpr lazy_init() noexcept : _init(false) {}
210 
211  constexpr void emplace()
212  {
213  LEXY_PRECONDITION(!*this);
214  _init = true;
215  }
216  template <typename Fn, typename... Args>
217  constexpr void emplace_result(Fn&& fn, Args&&... args)
218  {
219  LEXY_FWD(fn)(LEXY_FWD(args)...);
220  _init = true;
221  }
222 
223  constexpr explicit operator bool() const noexcept
224  {
225  return _init;
226  }
227 
228 private:
229  bool _init;
230 };
231 } // namespace lexy::_detail
232 
233 #endif // LEXY_DETAIL_LAZY_INIT_HPP_INCLUDED
234 
LEXY_MOV
#define LEXY_MOV(...)
Definition: config.hpp:21
lexy::_detail::lazy_init< T & >::lazy_init
constexpr lazy_init() noexcept
Definition: lazy_init.hpp:168
lexy::_detail::lazy_init< T & >::operator->
constexpr T * operator->() const noexcept
Definition: lazy_init.hpp:194
lexy::_detail::_lazy_init_storage_non_trivial::operator=
_lazy_init_storage_non_trivial & operator=(_lazy_init_storage_non_trivial &&other) noexcept
Definition: lazy_init.hpp:60
lexy::_detail::lazy_init::operator*
constexpr T && operator*() &&noexcept
Definition: lazy_init.hpp:134
lexy::_detail::_lazy_init_storage_trivial::_value
T _value
Definition: lazy_init.hpp:19
config.hpp
lexy::_detail::lazy_init::operator*
constexpr const T && operator*() const &&noexcept
Definition: lazy_init.hpp:139
lexy::_detail::lazy_init::lazy_init
constexpr lazy_init(int, Args &&... args) noexcept
Definition: lazy_init.hpp:158
lexy::_detail::lazy_init< void >::emplace_result
constexpr void emplace_result(Fn &&fn, Args &&... args)
Definition: lazy_init.hpp:217
lexy::_detail::lazy_init< void >::value_type
void value_type
Definition: lazy_init.hpp:207
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:22
lexy::_detail::_lazy_init_storage_non_trivial
Definition: lazy_init.hpp:31
lexy::_detail::lazy_init::emplace_result
constexpr T & emplace_result(Fn &&fn, Args &&... args)
Definition: lazy_init.hpp:114
lexy::_detail::_lazy_init_storage_non_trivial::_lazy_init_storage_non_trivial
constexpr _lazy_init_storage_non_trivial(int, Args &&... args)
Definition: lazy_init.hpp:43
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
lexy::_detail::_lazy_init_storage_trivial::_init
bool _init
Definition: lazy_init.hpp:15
lexy::_detail::lazy_init< void >::_init
bool _init
Definition: lazy_init.hpp:229
detail::void
j template void())
Definition: json.hpp:4893
lexy::_detail::_lazy_init_storage_non_trivial::_lazy_init_storage_non_trivial
_lazy_init_storage_non_trivial(_lazy_init_storage_non_trivial &&other) noexcept
Definition: lazy_init.hpp:53
lexy::_detail::_lazy_init_storage_trivial::_lazy_init_storage_trivial
constexpr _lazy_init_storage_trivial() noexcept
Definition: lazy_init.hpp:22
lexy::_detail::lazy_init::operator->
constexpr const T * operator->() const noexcept
Definition: lazy_init.hpp:150
lexy::_detail::lazy_init::emplace
constexpr T & emplace(Args &&... args)
Definition: lazy_init.hpp:105
lexy::_detail::lazy_init
Definition: lazy_init.hpp:97
lexy::_detail::lazy_init< T & >::emplace_result
constexpr T & emplace_result(Fn &&fn, Args &&... args)
Definition: lazy_init.hpp:178
assert.hpp
lexy::_detail::_lazy_init_storage
std::conditional_t< _lazy_init_trivial< T >, _lazy_init_storage_trivial< T >, _lazy_init_storage_non_trivial< T > > _lazy_init_storage
Definition: lazy_init.hpp:94
lexy::_detail::_lazy_init_storage_trivial
Definition: lazy_init.hpp:13
lexy::_detail::_lazy_init_storage_non_trivial::_value
T _value
Definition: lazy_init.hpp:37
lexy::_detail
Definition: any_ref.hpp:12
lexy::_detail::_lazy_init_storage_non_trivial::_lazy_init_storage_non_trivial
constexpr _lazy_init_storage_non_trivial() noexcept
Definition: lazy_init.hpp:40
lexy::_detail::_lazy_init_storage_trivial::_lazy_init_storage_trivial
constexpr _lazy_init_storage_trivial(int, Args &&... args)
Definition: lazy_init.hpp:25
lexy::_detail::_lazy_init_storage_non_trivial::~_lazy_init_storage_non_trivial
~_lazy_init_storage_non_trivial() noexcept
Definition: lazy_init.hpp:47
lexy::_detail::lazy_init::operator->
constexpr T * operator->() noexcept
Definition: lazy_init.hpp:145
lexy::_detail::lazy_init::operator*
constexpr T & operator*() &noexcept
Definition: lazy_init.hpp:124
lexy::_detail::lazy_init< T & >::emplace
constexpr T & emplace(T &ref)
Definition: lazy_init.hpp:170
lexy::_detail::_lazy_init_trivial
constexpr auto _lazy_init_trivial
Definition: lazy_init.hpp:84
lexy::_detail::lazy_init::lazy_init
constexpr lazy_init() noexcept=default
lexy::_detail::lazy_init< T & >::value_type
T & value_type
Definition: lazy_init.hpp:166
lexy::_detail::lazy_init< T & >::operator*
constexpr T & operator*() const noexcept
Definition: lazy_init.hpp:188
lexy::_detail::lazy_init< void >::emplace
constexpr void emplace()
Definition: lazy_init.hpp:211
lexy::_detail::lazy_init< void >::lazy_init
constexpr lazy_init() noexcept
Definition: lazy_init.hpp:209
lexy::_detail::_lazy_init_storage_non_trivial::_empty
char _empty
Definition: lazy_init.hpp:36
lexy::_detail::_lazy_init_storage_trivial::_empty
char _empty
Definition: lazy_init.hpp:18
lexy::_detail::_lazy_init_storage_non_trivial::_init
bool _init
Definition: lazy_init.hpp:33
lexy::_detail::lazy_init::operator*
constexpr const T & operator*() const &noexcept
Definition: lazy_init.hpp:129
lexy::input_location_anchor
Anchor for the location search.
Definition: input_location.hpp:17
lexy::_detail::lazy_init< T & >::_ptr
T * _ptr
Definition: lazy_init.hpp:201


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07