PLSSVM - Parallel Least Squares Support Vector Machine  2.0.0
A Least Squares Support Vector Machine implementation using different backends.
default_value.hpp
Go to the documentation of this file.
1 
12 #ifndef PLSSVM_DEFAULT_VALUE_HPP_
13 #define PLSSVM_DEFAULT_VALUE_HPP_
14 #pragma once
15 
16 #include "plssvm/detail/type_traits.hpp" // PLSSVM_REQUIRES
17 
18 #include <cstddef> // std::size_t
19 #include <functional> // std::hash
20 #include <istream> // std::istream
21 #include <ostream> // std::ostream
22 #include <type_traits> // std::is_nothrow_default_constructible_v, std::is_nothrow_move_constructible_v, std::is_nothrow_move_assignable_v, std::is_nothrow_swappable_v,
23  // std::is_convertible_v, std::true_type, std::false_type, std::remove_reference_t, std::remove_cv_t
24 #include <utility> // std::move_if_noexcept, std::swap
25 
26 namespace plssvm {
27 
28 //*************************************************************************************************************************************//
29 // default_init //
30 //*************************************************************************************************************************************//
31 
36 template <typename T>
37 struct default_init {
41  constexpr default_init() noexcept(std::is_nothrow_default_constructible_v<T>) = default;
46  constexpr explicit default_init(T val) noexcept(std::is_nothrow_move_constructible_v<T>) :
47  value{ std::move_if_noexcept(val) } {}
48 
50  T value{};
51 };
52 
53 //*************************************************************************************************************************************//
54 // default_value //
55 //*************************************************************************************************************************************//
56 
61 template <typename T>
64  // befriend a default_value encapsulating another type (used to be able to convert between, e.g., default_value<int> and default_value<float>)
65  template <typename>
66  friend class default_value;
67  // befriend input stream operator to be able to construct a default_value from a std::istream
68  template <typename U>
69  friend std::istream &operator>>(std::istream &in, default_value<U> &);
71 
72  public:
74  using value_type = T;
75 
81  constexpr explicit default_value(default_init<value_type> default_val = default_init<value_type>{}) noexcept(std::is_nothrow_move_constructible_v<value_type>) :
82  default_init_{ std::move_if_noexcept(default_val) } {}
89  constexpr default_value &operator=(value_type non_default_val) noexcept(std::is_nothrow_move_assignable_v<value_type>) {
90  value_ = std::move_if_noexcept(non_default_val);
91  use_default_init_ = false;
92  return *this;
93  }
94 
101  template <typename U, PLSSVM_REQUIRES(std::is_convertible_v<U, value_type>)>
102  constexpr explicit default_value(const default_value<U> &other) noexcept(std::is_nothrow_copy_constructible_v<U>) :
103  value_{ static_cast<value_type>(other.value_) },
105  default_init_{ static_cast<value_type>(other.default_init_.value) } {}
112  template <typename U, PLSSVM_REQUIRES(std::is_convertible_v<U, value_type>)>
113  constexpr explicit default_value(default_value<U> &&other) noexcept(std::is_nothrow_move_constructible_v<U>) :
114  value_{ static_cast<value_type>(std::move_if_noexcept(other.value_)) },
116  default_init_{ static_cast<value_type>(std::move_if_noexcept(other.default_init_.value)) } {}
124  template <typename U, PLSSVM_REQUIRES(std::is_convertible_v<U, value_type>)>
125  constexpr default_value &operator=(const default_value<U> &other) noexcept(std::is_nothrow_copy_assignable_v<U>) {
126  value_ = static_cast<value_type>(other.value_);
127  use_default_init_ = other.use_default_init_;
128  default_init_ = default_init<value_type>{ static_cast<value_type>(other.default_init_.value) };
129  return *this;
130  }
138  template <typename U, PLSSVM_REQUIRES(std::is_convertible_v<U, value_type>)>
139  constexpr default_value &operator=(default_value<U> &&other) noexcept(std::is_nothrow_move_assignable_v<U>) {
140  value_ = static_cast<value_type>(std::move_if_noexcept(other.value_));
141  use_default_init_ = other.use_default_init_;
142  default_init_ = default_init<value_type>{ static_cast<value_type>(std::move_if_noexcept(other.default_init_.value)) };
143  return *this;
144  }
145 
150  [[nodiscard]] constexpr const value_type &value() const noexcept {
151  return this->is_default() ? default_init_.value : value_;
152  }
156  [[nodiscard]] constexpr operator const value_type &() const noexcept {
157  return this->value();
158  }
163  [[nodiscard]] constexpr const value_type &get_default() const noexcept {
164  return default_init_.value;
165  }
170  [[nodiscard]] constexpr bool is_default() const noexcept {
171  return use_default_init_;
172  }
173 
178  constexpr void swap(default_value &other) noexcept(std::is_nothrow_swappable_v<T>) {
179  using std::swap;
180  swap(value_, other.value_);
181  swap(use_default_init_, other.use_default_init_);
182  swap(default_init_, other.default_init_);
183  }
187  constexpr void reset() noexcept {
188  use_default_init_ = true;
189  }
190 
191  private:
195  bool use_default_init_{ true };
198 };
199 
207 template <typename T>
208 inline std::ostream &operator<<(std::ostream &out, const default_value<T> &val) {
209  return out << val.value();
210 }
219 template <typename T>
220 inline std::istream &operator>>(std::istream &in, default_value<T> &val) {
221  in >> val.value_;
222  val.use_default_init_ = false;
223  return in;
224 }
225 
231 template <typename T>
232 constexpr void swap(default_value<T> &lhs, default_value<T> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
233  lhs.swap(rhs);
234 }
235 
243 template <typename T>
244 [[nodiscard]] constexpr bool operator==(const default_value<T> &lhs, const default_value<T> &rhs) noexcept {
245  return lhs.value() == rhs.value();
246 }
250 template <typename T>
251 [[nodiscard]] constexpr bool operator==(const default_value<T> &lhs, const T &rhs) noexcept {
252  return lhs.value() == rhs;
253 }
257 template <typename T>
258 [[nodiscard]] constexpr bool operator==(const T &lhs, const default_value<T> &rhs) noexcept {
259  return lhs == rhs.value();
260 }
261 
269 template <typename T>
270 [[nodiscard]] constexpr bool operator!=(const default_value<T> &lhs, const default_value<T> &rhs) noexcept {
271  return !(lhs == rhs);
272 }
276 template <typename T>
277 [[nodiscard]] constexpr bool operator!=(const default_value<T> &lhs, const T &rhs) noexcept {
278  return !(lhs == rhs);
279 }
283 template <typename T>
284 [[nodiscard]] constexpr bool operator!=(const T &lhs, const default_value<T> &rhs) noexcept {
285  return !(lhs == rhs);
286 }
287 
295 template <typename T>
296 [[nodiscard]] constexpr bool operator<(const default_value<T> &lhs, const default_value<T> &rhs) noexcept {
297  return lhs.value() < rhs.value();
298 }
302 template <typename T>
303 [[nodiscard]] constexpr bool operator<(const default_value<T> &lhs, const T &rhs) noexcept {
304  return lhs.value() < rhs;
305 }
309 template <typename T>
310 [[nodiscard]] constexpr bool operator<(const T &lhs, const default_value<T> &rhs) noexcept {
311  return lhs < rhs.value();
312 }
313 
321 template <typename T>
322 [[nodiscard]] constexpr bool operator>(const default_value<T> &lhs, const default_value<T> &rhs) noexcept {
323  return rhs < lhs;
324 }
325 
329 template <typename T>
330 [[nodiscard]] constexpr bool operator>(const default_value<T> &lhs, const T &rhs) noexcept {
331  return lhs.value() > rhs;
332 }
333 
337 template <typename T>
338 [[nodiscard]] constexpr bool operator>(const T &lhs, const default_value<T> &rhs) noexcept {
339  return lhs > rhs.value();
340 }
341 
349 template <typename T>
350 [[nodiscard]] constexpr bool operator<=(const default_value<T> &lhs, const default_value<T> &rhs) noexcept {
351  return !(lhs > rhs);
352 }
356 template <typename T>
357 [[nodiscard]] constexpr bool operator<=(const default_value<T> &lhs, const T &rhs) noexcept {
358  return !(lhs.value() > rhs);
359 }
363 template <typename T>
364 [[nodiscard]] constexpr bool operator<=(const T &lhs, const default_value<T> &rhs) noexcept {
365  return !(lhs > rhs.value());
366 }
367 
375 template <typename T>
376 [[nodiscard]] constexpr bool operator>=(const default_value<T> &lhs, const default_value<T> &rhs) noexcept {
377  return !(lhs < rhs);
378 }
382 template <typename T>
383 [[nodiscard]] constexpr bool operator>=(const default_value<T> &lhs, const T &rhs) noexcept {
384  return !(lhs.value() < rhs);
385 }
389 template <typename T>
390 [[nodiscard]] constexpr bool operator>=(const T &lhs, const default_value<T> &rhs) noexcept {
391  return !(lhs < rhs.value());
392 }
393 
395 namespace detail {
396 
402 template <typename T>
403 struct is_default_value : std::false_type {};
409 template <typename T>
410 struct is_default_value<default_value<T>> : std::true_type {};
411 
412 } // namespace detail
414 
419 template <typename T>
420 struct is_default_value : detail::is_default_value<std::remove_cv_t<std::remove_reference_t<T>>> {}; // can't use detail::remove_cvref_t because of circular dependencies
424 template <typename T>
426 
427 } // namespace plssvm
428 
429 namespace std {
430 
435 template <typename T>
436 struct hash<plssvm::default_value<T>> {
443  std::size_t operator()(const plssvm::default_value<T> &val) const noexcept {
444  return std::hash<T>{}(val.value());
445  }
446 };
447 
448 } // namespace std
449 
450 #endif // PLSSVM_DEFAULT_VALUE_HPP_
This class encapsulates a value that may be a default value or not.
Definition: default_value.hpp:62
bool use_default_init_
Flag used to determine whether the default value should be used or the user defined value.
Definition: default_value.hpp:195
constexpr default_value & operator=(value_type non_default_val) noexcept(std::is_nothrow_move_assignable_v< value_type >)
Override the previously provided default value with the new, non-default value.
Definition: default_value.hpp:89
value_type value_
The wrapped value to be used if use_default_init_ is false.
Definition: default_value.hpp:193
constexpr default_value(default_value< U > &&other) noexcept(std::is_nothrow_move_constructible_v< U >)
Move-construct a new default_value_from a possibly other type.
Definition: default_value.hpp:113
constexpr void swap(default_value &other) noexcept(std::is_nothrow_swappable_v< T >)
Swap the content of two default_values.
Definition: default_value.hpp:178
constexpr default_value(const default_value< U > &other) noexcept(std::is_nothrow_copy_constructible_v< U >)
Copy-construct a new default_value from a possibly other type.
Definition: default_value.hpp:102
constexpr default_value & operator=(default_value< U > &&other) noexcept(std::is_nothrow_move_assignable_v< U >)
Move-assign a new default_value from a possible other type.
Definition: default_value.hpp:139
T value_type
The type encapsulated by this default_value.
Definition: default_value.hpp:74
constexpr const value_type & value() const noexcept
Get the currently active value: the user provided value if provided, otherwise the default value is r...
Definition: default_value.hpp:150
constexpr const value_type & get_default() const noexcept
Get the default value even if it has already been overwritten by the user.
Definition: default_value.hpp:163
default_init< value_type > default_init_
The wrapped default value used if use_default_init_ is true.
Definition: default_value.hpp:197
constexpr bool is_default() const noexcept
Check whether the currently active value is the default value.
Definition: default_value.hpp:170
constexpr default_value(default_init< value_type > default_val=default_init< value_type >{}) noexcept(std::is_nothrow_move_constructible_v< value_type >)
Copy construct a default_value object using the provided default value.
Definition: default_value.hpp:81
constexpr void reset() noexcept
Set the current active value back to the default value.
Definition: default_value.hpp:187
constexpr default_value & operator=(const default_value< U > &other) noexcept(std::is_nothrow_copy_assignable_v< U >)
Copy-assign a new default_value from a possible other type.
Definition: default_value.hpp:125
The main namespace containing all public API functions.
Definition: backend_types.hpp:24
constexpr bool is_default_value_v
Test whether the given type T is of type plssvm::default_value ignoring all top-level const,...
Definition: default_value.hpp:425
constexpr void swap(default_value< T > &lhs, default_value< T > &rhs) noexcept(noexcept(lhs.swap(rhs)))
Swap the content of two default_values lhs and rhs.
Definition: default_value.hpp:232
std::istream & operator>>(std::istream &in, backend_type &backend)
Use the input-stream in to initialize the backend type.
constexpr bool operator<=(const default_value< T > &lhs, const default_value< T > &rhs) noexcept
Compares the two active values: lhs <= rhs.
Definition: default_value.hpp:350
constexpr bool operator<(const default_value< T > &lhs, const default_value< T > &rhs) noexcept
Compares the two active values: lhs < rhs.
Definition: default_value.hpp:296
constexpr bool operator>(const default_value< T > &lhs, const default_value< T > &rhs) noexcept
Compares the two active values: lhs > rhs.
Definition: default_value.hpp:322
std::ostream & operator<<(std::ostream &out, backend_type backend)
Output the backend to the given output-stream out.
constexpr bool operator!=(const default_value< T > &lhs, const default_value< T > &rhs) noexcept
Compares the two active values lhs and rhs for inequality.
Definition: default_value.hpp:270
constexpr bool operator>=(const default_value< T > &lhs, const default_value< T > &rhs) noexcept
Compares the two active values: lhs >= rhs.
Definition: default_value.hpp:376
constexpr bool operator==(const default_value< T > &lhs, const default_value< T > &rhs) noexcept
Compares the two active values lhs and rhs for equality.
Definition: default_value.hpp:244
This class denotes an explicit default value initialization used to distinguish between the default v...
Definition: default_value.hpp:37
constexpr default_init() noexcept(std::is_nothrow_default_constructible_v< T >)=default
Default construct the default initialization value.
T value
The explicit default initialization value.
Definition: default_value.hpp:50
Test whether the given type T is of type plssvm::default_value ignoring all top-level const,...
Definition: default_value.hpp:420
std::size_t operator()(const plssvm::default_value< T > &val) const noexcept
Overload the function call operator for a default_value.
Definition: default_value.hpp:443
Defines some generic type traits used in the PLSSVM library.