OGLplus  (0.59.0) a C++ wrapper for rendering APIs

base.hpp
Go to the documentation of this file.
1 
9 #ifndef EAGINE_VALID_IF_BASE_HPP
10 #define EAGINE_VALID_IF_BASE_HPP
11 
12 #include "../assert.hpp"
13 #include "../branch_predict.hpp"
14 #include <sstream>
15 #include <stdexcept>
16 #include <type_traits>
17 #include <utility>
18 
19 namespace eagine {
20 
25 template <typename T>
27 public:
29  constexpr basic_valid_if_value(T value) noexcept(
30  noexcept(T(std::declval<T&&>())))
31  : _value{std::move(value)} {}
32 
34  constexpr basic_valid_if_value() noexcept(
35  std::is_nothrow_default_constructible_v<T>) = default;
36 
38  constexpr basic_valid_if_value(basic_valid_if_value&&) noexcept(
39  std::is_nothrow_move_constructible_v<T>) = default;
40 
42  constexpr basic_valid_if_value(const basic_valid_if_value&) noexcept(
43  std::is_nothrow_copy_constructible_v<T>) = default;
44 
46  auto operator=(basic_valid_if_value&&) noexcept(
47  std::is_nothrow_move_assignable_v<T>) -> basic_valid_if_value& = default;
48 
50  auto operator=(const basic_valid_if_value&) noexcept(
51  std::is_nothrow_copy_assignable_v<T>) -> basic_valid_if_value& = default;
52 
54  ~basic_valid_if_value() noexcept = default;
55 
57  auto operator=(const T& v) -> auto& {
58  _value = v;
59  return *this;
60  }
61 
63  auto operator=(T&& v) -> auto& {
64  _value = std::move(v);
65  return *this;
66  }
67 
68 protected:
69  auto _ref_value() noexcept -> auto& {
70  return _value;
71  }
72 
73  constexpr auto _get_value() const noexcept -> auto& {
74  return _value;
75  }
76 
77 private:
78  T _value{};
79 };
80 
85 template <typename T, typename Policy, typename DoLog, typename... P>
87  : public basic_valid_if_value<T>
88  , private Policy
89  , private DoLog {
90 private:
91  auto _do_log() const noexcept -> const DoLog& {
92  return *this;
93  }
94 
95  explicit constexpr basic_valid_if(Policy plcy) noexcept
96  : Policy(plcy)
97  , DoLog(policy()) {}
98 
99 public:
101  [[nodiscard]] auto policy() const noexcept -> const Policy& {
102  return *this;
103  }
104 
106  constexpr basic_valid_if() noexcept
107  : DoLog(policy()) {}
108 
110  constexpr basic_valid_if(T val) noexcept
111  : basic_valid_if_value<T>(std::move(val))
112  , DoLog(policy()) {}
113 
115  constexpr basic_valid_if(T val, Policy plcy) noexcept
116  : basic_valid_if_value<T>(std::move(val))
117  , Policy(std::move(plcy))
118  , DoLog(policy()) {}
119 
121  constexpr basic_valid_if(const basic_valid_if& that)
123  static_cast<const basic_valid_if_value<T>&>(that))
124  , Policy(static_cast<const Policy&>(that))
125  , DoLog(policy()) {}
126 
128  basic_valid_if(basic_valid_if&& that) noexcept(
129  std::is_nothrow_move_constructible_v<T>)
130  : basic_valid_if_value<T>(static_cast<basic_valid_if_value<T>&&>(that))
131  , Policy(static_cast<Policy&&>(that))
132  , DoLog(policy()) {}
133 
135  // NOLINTNEXTLINE(bugprone-unhandled-self-assignment,cert-oop54-cpp)
136  auto operator=(const basic_valid_if& that) -> auto& {
137  if(this != std::addressof(that)) {
138  static_cast<basic_valid_if_value<T>&>(*this) =
139  static_cast<const basic_valid_if_value<T>&>(that);
140  static_cast<Policy&>(*this) = static_cast<const Policy&>(that);
141  static_cast<DoLog&>(*this) = {policy()};
142  }
143  return *this;
144  }
145 
147  auto operator=(basic_valid_if&& that) noexcept(
148  std::is_nothrow_move_assignable_v<T>) -> auto& {
149  if(this != std::addressof(that)) {
150  static_cast<basic_valid_if_value<T>&>(*this) =
151  static_cast<basic_valid_if_value<T>&&>(that);
152  static_cast<Policy&>(*this) = static_cast<Policy&&>(that);
153  static_cast<DoLog&>(*this) = DoLog(policy());
154  }
155  return *this;
156  }
157 
159  auto operator=(const T& value) -> auto& {
160  static_cast<basic_valid_if_value<T>&>(*this) =
161  static_cast<const basic_valid_if_value<T>&>(value);
162  return *this;
163  }
164 
165  auto operator=(T& value) -> auto& {
166  static_cast<basic_valid_if_value<T>&>(*this) =
167  static_cast<basic_valid_if_value<T>&&>(value);
168  return *this;
169  }
170 
172  ~basic_valid_if() noexcept = default;
173 
176  constexpr auto is_valid(const T& val, P... p) const noexcept -> bool {
177  return policy()(val, p...);
178  }
179 
182  constexpr auto is_valid(P... p) const noexcept {
183  return is_valid(this->_get_value(), p...);
184  }
185 
188  constexpr auto has_value(P... p) const noexcept {
189  return is_valid(p...);
190  }
191 
193  constexpr friend auto
194  operator==(const basic_valid_if& a, const basic_valid_if& b) noexcept
195  -> bool {
196  return (a._get_value() == b._get_value()) && a.is_valid() &&
197  b.is_valid();
198  }
199 
200  template <typename Log>
201  void log_invalid(Log& log, const T& v, P... p) const {
202  EAGINE_ASSERT(!is_valid(v, p...));
203  _do_log()(log, v, p...);
204  }
205 
206  template <typename Log>
207  void log_invalid(Log& log, P... p) const {
208  log_invalid(log, this->_get_value(), p...);
209  }
210 
214  template <typename Func>
215  auto call_if_invalid(Func func, P... p) -> auto& {
216  if(!is_valid(p...)) {
217  func(_do_log(), this->_get_value(), p...);
218  }
219  return *this;
220  }
221 
225  void throw_if_invalid(P... p) const {
226  if(!is_valid(p...)) {
227  std::stringstream ss;
228  log_invalid(ss, p...);
229  throw std::runtime_error(ss.str());
230  }
231  }
232 
236  auto value(P... p) -> T& {
237  throw_if_invalid(p...);
238  return this->_ref_value();
239  }
240 
244  auto value(P... p) const -> const T& {
245  throw_if_invalid(p...);
246  return this->_get_value();
247  }
248 
251  auto value_or(T& fallback, P... p) noexcept -> auto& {
252  return EAGINE_LIKELY(is_valid(p...)) ? this->_ref_value() : fallback;
253  }
254 
257  constexpr auto value_or(const T& fallback, P... p) const noexcept -> auto& {
258  return EAGINE_LIKELY(is_valid(p...)) ? this->_get_value() : fallback;
259  }
260 
262  constexpr auto value_anyway(P...) const noexcept -> auto& {
263  return this->_get_value();
264  }
265 
267  constexpr auto value_anyway(P...) noexcept -> auto& {
268  return this->_ref_value();
269  }
270 
274  template <typename Func>
275  auto then(const Func& func, P... p) const
276  -> std::enable_if_t<std::is_same_v<std::result_of_t<Func(T)>, void>> {
277  if(EAGINE_LIKELY(is_valid(p...))) {
278  func(value(p...));
279  }
280  }
281 
285  template <typename Func>
286  constexpr auto transformed(Func func, P... p) const noexcept {
287  return func(this->_get_value(), is_valid(p...));
288  }
289 };
290 
291 } // namespace eagine
292 
293 #endif // EAGINE_VALID_IF_BASE_HPP
constexpr auto has_value(P... p) const noexcept
Checks if the stored value is valid according to policy.
Definition: base.hpp:188
auto operator=(T &&v) -> auto &
Moves v to the stored value.
Definition: base.hpp:63
constexpr auto value_anyway(P...) const noexcept -> auto &
Returns the stored value regardless of its validity.
Definition: base.hpp:262
constexpr basic_valid_if(T val) noexcept
Constructor initializing the stored value by val.
Definition: base.hpp:110
constexpr friend auto operator==(const basic_valid_if &a, const basic_valid_if &b) noexcept -> bool
Equality comparison.
Definition: base.hpp:194
Common code is placed in this namespace.
Definition: eagine.hpp:21
constexpr basic_valid_if_value(T value) noexcept(noexcept(T(std::declval< T && >())))
Initializing constructor.
Definition: base.hpp:29
auto call_if_invalid(Func func, P... p) -> auto &
Calls the specified function if the stored value is invalid.
Definition: base.hpp:215
constexpr basic_valid_if(const basic_valid_if &that)
Copy constructor.
Definition: base.hpp:121
auto operator=(const basic_valid_if &that) -> auto &
Copy assignment operator.
Definition: base.hpp:136
auto policy() const noexcept -> const Policy &
Returns a reference to this object's policy.
Definition: base.hpp:101
constexpr basic_valid_if(T val, Policy plcy) noexcept
Constructor initializing the stored value and policy.
Definition: base.hpp:115
auto operator=(const T &value) -> auto &
Copies value into this instance.
Definition: base.hpp:159
constexpr auto is_valid(const T &val, P... p) const noexcept -> bool
Checks if val is valid according to this object's policy.
Definition: base.hpp:176
constexpr auto transformed(Func func, P... p) const noexcept
Calls a binary transforming function on {value, is_valid()} pair.
Definition: base.hpp:286
~basic_valid_if() noexcept=default
The destructor.
Base class for basic_valid_if, storing the conditionally valid value.
Definition: base.hpp:26
auto then(const Func &func, P... p) const -> std::enable_if_t< std::is_same_v< std::result_of_t< Func(T)>, void >>
Calls the specified function if the stored value is valid.
Definition: base.hpp:275
void throw_if_invalid(P... p) const
Throws an exception if the stored value is invalid.
Definition: base.hpp:225
auto value_or(T &fallback, P... p) noexcept -> auto &
Returns the stored value if valid, otherwise returns fallback.
Definition: base.hpp:251
constexpr auto value_anyway(P...) noexcept -> auto &
Returns the stored value regardless of its validity.
Definition: base.hpp:267
basic_valid_if(basic_valid_if &&that) noexcept(std::is_nothrow_move_constructible_v< T >)
Move constructor.
Definition: base.hpp:128
constexpr basic_valid_if_value() noexcept(std::is_nothrow_default_constructible_v< T >)=default
Default constructor.
constexpr basic_valid_if() noexcept
Default constructor.
Definition: base.hpp:106
auto value(P... p) -> T &
Returns the stored value if it is valid otherwise throws.
Definition: base.hpp:236
auto operator=(basic_valid_if &&that) noexcept(std::is_nothrow_move_assignable_v< T >) -> auto &
Move assignment operator.
Definition: base.hpp:147
Basic template for conditionally-valid values.
Definition: base.hpp:86

Copyright © 2015-2021 Matúš Chochlík.
<chochlik -at -gmail.com>
Documentation generated on Tue Apr 13 2021 by Doxygen (version 1.8.17).