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  is_none = false;
50  new (&val) T(value);
51  }
53  optional(const optional<T>& other) {
54  is_none = other.is_none;
55  if (!is_none) {
56  new (&val) T(other.value());
57  }
58  }
61  if (!is_none) {
62  reinterpret_cast<T*>(&val)->~T();
63  }
64  }
66  void swap(optional<T>& other) {
67  std::swap(val, other.val);
68  std::swap(is_none, other.is_none);
69  }
74  optional<T>& operator=(const T& value) {
75  (optional<T>(value)).swap(*this);
76  return *this;
77  }
83  (optional<T>(other)).swap(*this);
84  return *this;
85  }
90  (optional<T>()).swap(*this);
91  return *this;
92  }
94  T& operator*() { // NOLINT(*)
95  return *reinterpret_cast<T*>(&val);
96  }
98  const T& operator*() const {
99  return *reinterpret_cast<const T*>(&val);
100  }
102  bool operator==(const optional<T>& other) const {
103  return this->is_none == other.is_none &&
104  (this->is_none == true || this->value() == other.value());
105  }
109  const T& value() const {
110  if (is_none) {
111  throw std::logic_error("bad optional access");
112  }
113  return *reinterpret_cast<const T*>(&val);
114  }
116  explicit operator bool() const { return !is_none; }
118  bool has_value() const { return operator bool(); }
119 
120  private:
121  // whether this is none
122  bool is_none;
123  // on stack storage of value
124  typename std::aligned_storage<sizeof(T), alignof(T)>::type val;
125 };
126 
140 template<typename T>
141 std::ostream &operator<<(std::ostream &os, const optional<T> &t) {
142  if (t) {
143  os << *t;
144  } else {
145  os << "None";
146  }
147  return os;
148 }
149 
167 template<typename T>
168 std::istream &operator>>(std::istream &is, optional<T> &t) {
169  char buf[4];
170  std::streampos origin = is.tellg();
171  is.read(buf, 4);
172  if (is.fail() || buf[0] != 'N' || buf[1] != 'o' ||
173  buf[2] != 'n' || buf[3] != 'e') {
174  is.clear();
175  is.seekg(origin);
176  T x;
177  is >> x;
178  t = x;
179  if (std::is_integral<T>::value && !is.eof() && is.peek() == 'L') is.get();
180  } else {
181  t = nullopt;
182  }
183  return is;
184 }
205 inline std::istream &operator>>(std::istream &is, optional<bool> &t) {
206  // Discard initial whitespace
207  while (isspace(is.peek()))
208  is.get();
209  // Extract chars that might be valid into a separate string, stopping
210  // on whitespace or other non-alphanumerics such as ",)]".
211  std::string s;
212  while (isalnum(is.peek()))
213  s.push_back(is.get());
214 
215  if (!is.fail()) {
216  std::transform(s.begin(), s.end(), s.begin(), ::tolower);
217  if (s == "1" || s == "true")
218  t = true;
219  else if (s == "0" || s == "false")
220  t = false;
221  else if (s == "none")
222  t = nullopt;
223  else
224  is.setstate(std::ios::failbit);
225  }
226 
227  return is;
228 }
229 
231 DMLC_DECLARE_TYPE_NAME(optional<int>, "int or None");
233 DMLC_DECLARE_TYPE_NAME(optional<bool>, "boolean or None");
235 DMLC_DECLARE_TYPE_NAME(optional<float>, "float or None");
237 DMLC_DECLARE_TYPE_NAME(optional<double>, "double or None");
238 
239 } // namespace dmlc
240 
241 namespace std {
243 template<typename T>
244 struct hash<dmlc::optional<T> > {
250  size_t operator()(const dmlc::optional<T>& val) const {
251  std::hash<bool> hash_bool;
252  size_t res = hash_bool(val.has_value());
253  if (val.has_value()) {
254  res = dmlc::HashCombine(res, val.value());
255  }
256  return res;
257  }
258 };
259 } // namespace std
260 
261 #endif // DMLC_OPTIONAL_H_
c++17 compatible optional class.
Definition: optional.h:43
~optional()
deconstructor
Definition: optional.h:60
size_t operator()(const dmlc::optional< T > &val) const
returns hash of the optional value.
Definition: optional.h:250
optional(const T &value)
construct an optional object with value
Definition: optional.h:48
Definition: optional.h:241
std::istream & operator>>(std::istream &is, optional< T > &t)
parse a string object into optional<T>
Definition: optional.h:168
optional(const optional< T > &other)
construct an optional object with another optional object
Definition: optional.h:53
optional< T > & operator=(const T &value)
set this object to hold value
Definition: optional.h:74
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:89
namespace for dmlc
Definition: array_view.h:12
const T & value() const
return the holded value. throws std::logic_error if holding no value
Definition: optional.h:109
void swap(optional< T > &other)
swap two optional
Definition: optional.h:66
constexpr const nullopt_t nullopt
Definition: optional.h:33
bool operator==(const optional< T > &other) const
equal comparison
Definition: optional.h:102
optional< T > & operator=(const optional< T > &other)
set this object to hold the same value with other
Definition: optional.h:82
T & operator*()
non-const dereference operator
Definition: optional.h:94
constexpr nullopt_t(int a)
dummy constructor
Definition: optional.h:28
bool has_value() const
whether this object is holding a value (alternate form).
Definition: optional.h:118
defines some common utility function.
dummy type for assign null to optional
Definition: optional.h:22
DMLC_DECLARE_TYPE_NAME(optional< int >,"int or None")
description for optional int
const T & operator*() const
const dereference operator
Definition: optional.h:98
optional()
construct an optional object that contains no value
Definition: optional.h:46
type traits information header