mxnet
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 
19 namespace dmlc {
20 
22 struct nullopt_t {
23 #if defined(_MSC_VER) && _MSC_VER < 1900
24 
25  explicit nullopt_t(int a) {}
26 #else
27 
28  constexpr explicit nullopt_t(int a) {}
29 #endif
30 };
31 
33 constexpr const nullopt_t nullopt = nullopt_t(0);
34 
42 template<typename T>
43 class optional {
44  public:
46  optional() : is_none(true) {}
48  explicit optional(const T& value) {
49 #pragma GCC diagnostic push
50 #if __GNUC__ >= 6
51 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
52 #endif
53  is_none = false;
54  new (&val) T(value);
55 #pragma GCC diagnostic pop
56  }
58  optional(const optional<T>& other) {
59 #pragma GCC diagnostic push
60 #if __GNUC__ >= 6
61 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
62 #endif
63  is_none = other.is_none;
64  if (!is_none) {
65  new (&val) T(other.value());
66  }
67 #pragma GCC diagnostic pop
68  }
71  if (!is_none) {
72  reinterpret_cast<T*>(&val)->~T();
73  }
74  }
76  void swap(optional<T>& other) {
77  std::swap(val, other.val);
78  std::swap(is_none, other.is_none);
79  }
84  optional<T>& operator=(const T& value) {
85  (optional<T>(value)).swap(*this);
86  return *this;
87  }
93  (optional<T>(other)).swap(*this);
94  return *this;
95  }
100  (optional<T>()).swap(*this);
101  return *this;
102  }
104  T& operator*() { // NOLINT(*)
105  return *reinterpret_cast<T*>(&val);
106  }
108  const T& operator*() const {
109  return *reinterpret_cast<const T*>(&val);
110  }
112  bool operator==(const optional<T>& other) const {
113  return this->is_none == other.is_none &&
114  (this->is_none == true || this->value() == other.value());
115  }
119  const T& value() const {
120  if (is_none) {
121  throw std::logic_error("bad optional access");
122  }
123  return *reinterpret_cast<const T*>(&val);
124  }
126  explicit operator bool() const { return !is_none; }
128  bool has_value() const { return operator bool(); }
129 
130  private:
131  // whether this is none
132  bool is_none;
133  // on stack storage of value
134  typename std::aligned_storage<sizeof(T), alignof(T)>::type val;
135 };
136 
150 template<typename T>
151 std::ostream &operator<<(std::ostream &os, const optional<T> &t) {
152  if (t) {
153  os << *t;
154  } else {
155  os << "None";
156  }
157  return os;
158 }
159 
177 template<typename T>
178 std::istream &operator>>(std::istream &is, optional<T> &t) {
179  char buf[4];
180  std::streampos origin = is.tellg();
181  is.read(buf, 4);
182  if (is.fail() || buf[0] != 'N' || buf[1] != 'o' ||
183  buf[2] != 'n' || buf[3] != 'e') {
184  is.clear();
185  is.seekg(origin);
186  T x;
187  is >> x;
188  t = x;
189  if (std::is_integral<T>::value && !is.eof() && is.peek() == 'L') is.get();
190  } else {
191  t = nullopt;
192  }
193  return is;
194 }
215 inline std::istream &operator>>(std::istream &is, optional<bool> &t) {
216  // Discard initial whitespace
217  while (isspace(is.peek()))
218  is.get();
219  // Extract chars that might be valid into a separate string, stopping
220  // on whitespace or other non-alphanumerics such as ",)]".
221  std::string s;
222  while (isalnum(is.peek()))
223  s.push_back(is.get());
224 
225  if (!is.fail()) {
226  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
227  if (s == "1" || s == "true")
228  t = true;
229  else if (s == "0" || s == "false")
230  t = false;
231  else if (s == "none")
232  t = nullopt;
233  else
234  is.setstate(std::ios::failbit);
235  }
236 
237  return is;
238 }
239 
241 DMLC_DECLARE_TYPE_NAME(optional<int>, "int or None");
243 DMLC_DECLARE_TYPE_NAME(optional<bool>, "boolean or None");
245 DMLC_DECLARE_TYPE_NAME(optional<float>, "float or None");
247 DMLC_DECLARE_TYPE_NAME(optional<double>, "double or None");
248 
249 } // namespace dmlc
250 
251 namespace std {
253 template<typename T>
254 struct hash<dmlc::optional<T> > {
260  size_t operator()(const dmlc::optional<T>& val) const {
261  std::hash<bool> hash_bool;
262  size_t res = hash_bool(val.has_value());
263  if (val.has_value()) {
264  res = dmlc::HashCombine(res, val.value());
265  }
266  return res;
267  }
268 };
269 } // namespace std
270 
271 #endif // DMLC_OPTIONAL_H_
DMLC_DECLARE_TYPE_NAME(optional< int >, "int or None")
description for optional int
c++17 compatible optional class.
Definition: optional.h:43
~optional()
deconstructor
Definition: optional.h:70
optional(const T &value)
construct an optional object with value
Definition: optional.h:48
Definition: optional.h:251
std::istream & operator>>(std::istream &is, optional< T > &t)
parse a string object into optional<T>
Definition: optional.h:178
optional(const optional< T > &other)
construct an optional object with another optional object
Definition: optional.h:58
optional< T > & operator=(const T &value)
set this object to hold value
Definition: optional.h:84
bool operator==(const optional< T > &other) const
equal comparison
Definition: optional.h:112
size_t HashCombine(size_t key, const T &value)
hash an object and combines the key with previous keys
Definition: common.h:37
bool isspace(char c)
Inline implementation of isspace(). Tests whether the given character is a whitespace letter...
Definition: strtonum.h:26
optional< T > & operator=(nullopt_t)
clear the value this object is holding. optional<T> x = nullopt;
Definition: optional.h:99
namespace for dmlc
Definition: array_view.h:12
void swap(optional< T > &other)
swap two optional
Definition: optional.h:76
constexpr const nullopt_t nullopt
Definition: optional.h:33
const T & value() const
return the holded value. throws std::logic_error if holding no value
Definition: optional.h:119
const T & operator*() const
const dereference operator
Definition: optional.h:108
optional< T > & operator=(const optional< T > &other)
set this object to hold the same value with other
Definition: optional.h:92
size_t operator()(const dmlc::optional< T > &val) const
returns hash of the optional value.
Definition: optional.h:260
bool has_value() const
whether this object is holding a value (alternate form).
Definition: optional.h:128
T & operator*()
non-const dereference operator
Definition: optional.h:104
constexpr nullopt_t(int a)
dummy constructor
Definition: optional.h:28
defines some common utility function.
dummy type for assign null to optional
Definition: optional.h:22
optional()
construct an optional object that contains no value
Definition: optional.h:46
type traits information header