Medial Code Documentation
Loading...
Searching...
No Matches
optional.h
Go to the documentation of this file.
1
6#ifndef DMLC_OPTIONAL_H_
7#define DMLC_OPTIONAL_H_
8
9#include <iostream>
10#include <string>
11#include <utility>
12#include <algorithm>
13
14#include "./base.h"
15#include "./common.h"
16#include "./logging.h"
17#include "./type_traits.h"
18
19namespace dmlc {
20
22struct nullopt_t {
23#if defined(_MSC_VER) && _MSC_VER < 1900
25 explicit nullopt_t(int a) {}
26#else
28 constexpr explicit nullopt_t(int) {}
29#endif
30};
31
33constexpr const nullopt_t nullopt = nullopt_t(0);
35template <typename T> using decay_t = typename std::decay<T>::type;
36template <bool B, typename T = void>
37using enable_if_t = typename std::enable_if<B, T>::type;
38
42struct in_place_t {
43 explicit in_place_t() = default; // NOLINT(*)
44};
46static constexpr in_place_t in_place{};
47
51template <typename T> class optional;
52template <typename T, typename U, typename Other>
53using enable_constructor_from_other =
54 enable_if_t<std::is_constructible<T, Other>::value &&
55 !std::is_constructible<T, optional<U> &>::value &&
56 !std::is_constructible<T, optional<U> &&>::value &&
57 !std::is_convertible<optional<U> &, T>::value &&
58 !std::is_convertible<optional<U> &&, T>::value &&
59 !std::is_constructible<T, const optional<U> &>::value &&
60 !std::is_constructible<T, const optional<U> &&>::value &&
61 !std::is_convertible<const optional<U> &, T>::value &&
62 !std::is_convertible<const optional<U> &&, T>::value>;
63template <typename T, typename U>
64using enable_constructor_from_value =
65 enable_if_t<std::is_constructible<T, U &&>::value &&
66 !std::is_same<decay_t<U>, in_place_t>::value &&
67 !std::is_same<optional<T>, decay_t<U>>::value>;
75template <typename T>
76class optional {
77 public:
78 using value_type = T;
80 optional() : is_none(true) {}
82 optional(dmlc::nullopt_t) noexcept : is_none(true) {} // NOLINT(*)
84 optional(const optional<T>& other) {
85#pragma GCC diagnostic push
86#if __GNUC__ >= 6
87#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
88#endif
89 is_none = other.is_none;
90 if (!is_none) {
91 new (&val) T(other.value());
92 }
93#pragma GCC diagnostic pop
94 }
97 optional(optional &&other) noexcept(
98 std::is_nothrow_move_constructible<T>::value
99 &&std::is_nothrow_move_assignable<T>::value) {
100 if (!other.has_value()) {
101 reset();
102 } else if (has_value()) {
103 **this = std::move(*other);
104 } else {
105 new (&val) T(std::move(*other));
106 is_none = false;
107 }
108 }
111 template <typename... Args>
112 explicit optional(
113 enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>,
114 Args &&...args) {
115 new (&val) T(std::forward<Args>(args)...);
116 is_none = false;
117 }
120 template <typename U, typename... Args>
121 explicit optional(
122 enable_if_t<std::is_constructible<T, std::initializer_list<U> &,
123 Args &&...>::value,
124 in_place_t>,
125 std::initializer_list<U> ilist, Args &&...args) {
126 construct(ilist, std::forward<Args>(args)...);
127 }
129 template <typename U = value_type,
130 enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr,
131 enable_constructor_from_value<T, U> * = nullptr>
132 optional(U &&other) noexcept { // NOLINT(*)
133 new (&val) T(std::forward<U>(other));
134 is_none = false;
135 }
138 template <typename U = value_type,
139 enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr,
140 enable_constructor_from_value<T, U> * = nullptr>
141 explicit optional(U &&other) noexcept {
142 new (&val) T(std::forward<U>(other));
143 is_none = false;
144 }
146 template <typename U,
147 enable_constructor_from_other<T, U, const U &> * = nullptr,
148 enable_if_t<std::is_convertible<const U &, T>::value> * = nullptr>
149 optional(const optional<U> &other) {
150 if (other.has_value()) {
151 construct(*other);
152 }
153 }
155 template <typename U,
156 enable_constructor_from_other<T, U, const U &> * = nullptr,
157 enable_if_t<!std::is_convertible<const U &, T>::value> * = nullptr>
158 explicit optional(const optional<U> &other) {
159 if (other.has_value()) {
160 construct(*other);
161 }
162 }
164 template <typename U, enable_constructor_from_other<T, U, U &&> * = nullptr,
165 enable_if_t<std::is_convertible<U &&, T>::value> * = nullptr>
167 if (other.has_value()) {
168 construct(std::move(*other));
169 }
170 }
172 template <typename U, enable_constructor_from_other<T, U, U &&> * = nullptr,
173 enable_if_t<!std::is_convertible<U &&, T>::value> * = nullptr>
174 explicit optional(optional<U> &&other) {
175 if (other.has_value()) {
176 construct(std::move(*other));
177 }
178 }
180 void reset() noexcept {
181 if (!has_value())
182 return;
183 (**this).T::~T();
184 is_none = true;
185 }
188 if (!is_none) {
189 reinterpret_cast<T*>(&val)->~T();
190 }
191 }
193 void swap(optional<T>& other) {
194 std::swap(val, other.val);
195 std::swap(is_none, other.is_none);
196 }
202 (optional<T>(value)).swap(*this);
203 return *this;
204 }
210#pragma GCC diagnostic push
211#if __GNUC__ >= 6
212#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
213#endif
214 (optional<T>(other)).swap(*this);
215 return *this;
216#pragma GCC diagnostic pop
217 }
222 (optional<T>()).swap(*this);
223 return *this;
224 }
226 T& operator*() { // NOLINT(*)
227 return *reinterpret_cast<T*>(&val);
228 }
230 const T& operator*() const {
231 return *reinterpret_cast<const T*>(&val);
232 }
234 bool operator==(const optional<T>& other) const {
235 return this->is_none == other.is_none &&
236 (this->is_none == true || this->value() == other.value());
237 }
241 T &value() & {
242 if (is_none) {
243 throw std::logic_error("bad optional access");
244 }
245 return *reinterpret_cast<T *>(&val);
246 }
247 const T &value() const & {
248 if (is_none) {
249 throw std::logic_error("bad optional access");
250 }
251 return *reinterpret_cast<const T *>(&val);
252 }
253 T &&value() && {
254 if (is_none) {
255 throw std::logic_error("bad optional access");
256 }
257 return std::move(value());
258 }
259 const T &&value() const && {
260 if (is_none) {
261 throw std::logic_error("bad optional access");
262 }
263 return std::move(value());
264 }
266 explicit operator bool() const { return !is_none; }
268 bool has_value() const { return operator bool(); }
269
270 private:
271 // whether this is none
272 bool is_none = true;
273 // on stack storage of value
274 typename std::aligned_storage<sizeof(T), alignof(T)>::type val;
275
276 template <typename... Args> void construct(Args &&...args) noexcept {
277 new (std::addressof(val)) T(std::forward<Args>(args)...);
278 is_none = false;
279 }
280};
281
295template<typename T>
296std::ostream &operator<<(std::ostream &os, const optional<T> &t) {
297 if (t) {
298 os << *t;
299 } else {
300 os << "None";
301 }
302 return os;
303}
304
322template<typename T>
323std::istream &operator>>(std::istream &is, optional<T> &t) {
324 char buf[4];
325 std::streampos origin = is.tellg();
326 is.read(buf, 4);
327 if (is.fail() || buf[0] != 'N' || buf[1] != 'o' ||
328 buf[2] != 'n' || buf[3] != 'e') {
329 is.clear();
330 is.seekg(origin);
331 T x;
332 is >> x;
333 t = x;
334 if (std::is_integral<T>::value && !is.eof() && is.peek() == 'L') is.get();
335 } else {
336 t = nullopt;
337 }
338 return is;
339}
360inline std::istream &operator>>(std::istream &is, optional<bool> &t) {
361 // Discard initial whitespace
362 while (isspace(is.peek()))
363 is.get();
364 // Extract chars that might be valid into a separate string, stopping
365 // on whitespace or other non-alphanumerics such as ",)]".
366 std::string s;
367 while (isalnum(is.peek()))
368 s.push_back(is.get());
369
370 if (!is.fail()) {
371 std::transform(s.begin(), s.end(), s.begin(), ::tolower);
372 if (s == "1" || s == "true")
373 t = true;
374 else if (s == "0" || s == "false")
375 t = false;
376 else if (s == "none")
377 t = nullopt;
378 else
379 is.setstate(std::ios::failbit);
380 }
381
382 return is;
383}
384
393
394} // namespace dmlc
395
396namespace std {
398template<typename T>
399struct hash<dmlc::optional<T> > {
405 size_t operator()(const dmlc::optional<T>& val) const {
406 std::hash<bool> hash_bool;
407 size_t res = hash_bool(val.has_value());
408 if (val.has_value()) {
409 res = dmlc::HashCombine(res, val.value());
410 }
411 return res;
412 }
413};
414} // namespace std
415
416#endif // DMLC_OPTIONAL_H_
Is not constructible or convertible from any expression of type (possibly const) dmlc::optional<U>,...
Definition optional.h:76
optional(U &&other) noexcept
constructs the stored value with value with other parameter.
Definition optional.h:132
optional(enable_if_t< std::is_constructible< T, std::initializer_list< U > &, Args &&... >::value, in_place_t >, std::initializer_list< U > ilist, Args &&...args)
Constructs an optional object that contains a value, initialized as if direct-initializing.
Definition optional.h:121
optional(const optional< T > &other)
construct an optional object with another optional object
Definition optional.h:84
bool has_value() const
whether this object is holding a value (alternate form).
Definition optional.h:268
optional(optional &&other) noexcept(std::is_nothrow_move_constructible< T >::value &&std::is_nothrow_move_assignable< T >::value)
move constructor: If other contains a value, then stored value is direct-intialized with it.
Definition optional.h:97
optional()
constructs an object that does not contain a value.
Definition optional.h:80
const T & operator*() const
const dereference operator
Definition optional.h:230
optional< T > & operator=(nullopt_t)
clear the value this object is holding. optional<T> x = nullopt;
Definition optional.h:221
optional(enable_if_t< std::is_constructible< T, Args... >::value, in_place_t >, Args &&...args)
constructs an optional object that contains a value, initialized as if direct-initializing
Definition optional.h:112
bool operator==(const optional< T > &other) const
equal comparison
Definition optional.h:234
optional(const optional< U > &other)
converting copy constructor
Definition optional.h:149
optional< T > & operator=(const T &value)
set this object to hold value
Definition optional.h:201
optional(optional< U > &&other)
converting move constructor
Definition optional.h:166
T & operator*()
non-const dereference operator
Definition optional.h:226
optional(dmlc::nullopt_t) noexcept
constructs an object that does contain a nullopt value.
Definition optional.h:82
~optional()
deconstructor
Definition optional.h:187
T & value() &
return the holded value. throws std::logic_error if holding no value
Definition optional.h:241
void reset() noexcept
reset
Definition optional.h:180
void swap(optional< T > &other)
swap two optional
Definition optional.h:193
optional< T > & operator=(const optional< T > &other)
set this object to hold the same value with other
Definition optional.h:209
defines console logging options for xgboost. Use to enforce unified print behavior.
namespace for dmlc
Definition array_view.h:12
bool isspace(char c)
Inline implementation of isspace(). Tests whether the given character is a whitespace letter.
Definition strtonum.h:26
typename std::decay< T >::type decay_t
C++14 aliases.
Definition optional.h:35
std::ostream & operator<<(std::ostream &os, const optional< T > &t)
serialize an optional object to string.
Definition optional.h:296
constexpr const nullopt_t nullopt
Definition optional.h:33
size_t HashCombine(size_t key, const T &value)
hash an object and combines the key with previous keys
Definition common.h:37
std::istream & operator>>(std::istream &is, optional< T > &t)
parse a string object into optional<T>
Definition optional.h:323
Definition StdDeque.h:58
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:24418
Macros common to all headers.
disambiguation tags that can be passed to the constructors of dmlc::optional. A tag type to tell cons...
Definition optional.h:42
dummy type for assign null to optional
Definition optional.h:22
constexpr nullopt_t(int)
dummy constructor
Definition optional.h:28
type traits information header
#define DMLC_DECLARE_TYPE_NAME(Type, Name)
macro to quickly declare traits information
Definition type_traits.h:133
Copyright 2015-2023 by XGBoost Contributors.