backports-optional.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2017 Regents of the University of California.
4  *
5  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6  *
7  * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License as published by the Free Software
9  * Foundation, either version 3 of the License, or (at your option) any later version.
10  *
11  * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14  *
15  * You should have received copies of the GNU General Public License and GNU Lesser
16  * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17  * <http://www.gnu.org/licenses/>.
18  *
19  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20  */
21 
42 #ifndef NDN_UTIL_BACKPORTS_OPTIONAL_HPP
43 #define NDN_UTIL_BACKPORTS_OPTIONAL_HPP
44 
45 #include "backports.hpp"
46 
47 #if (__cplusplus > 201402L) && NDN_CXX_HAS_INCLUDE(<optional>)
48 # include <optional>
49 # define NDN_CXX_HAVE_STD_OPTIONAL
50 #elif (__cplusplus > 201103L) && NDN_CXX_HAS_INCLUDE(<experimental/optional>)
51 # include <experimental/optional>
52 # if __cpp_lib_experimental_optional >= 201411
53 # define NDN_CXX_HAVE_EXPERIMENTAL_OPTIONAL
54 # endif
55 #endif
56 
57 #if defined(NDN_CXX_HAVE_STD_OPTIONAL)
58 
59 namespace ndn {
60 using std::optional;
61 using std::in_place;
62 using std::nullopt;
63 using std::bad_optional_access;
64 using std::make_optional;
65 } // namespace ndn
66 
67 #elif defined(NDN_CXX_HAVE_EXPERIMENTAL_OPTIONAL)
68 
69 namespace ndn {
70 using std::experimental::optional;
73 using std::experimental::bad_optional_access;
75 
76 template<typename T, typename... Args>
77 constexpr optional<T>
78 make_optional(Args&&... args)
79 {
80  return optional<T>(in_place, std::forward<Args>(args)...);
81 }
82 } // namespace ndn
83 
84 #else
85 
86 #include <boost/none.hpp>
87 #include <boost/optional.hpp>
88 #include <boost/utility/typed_in_place_factory.hpp>
89 
90 namespace ndn {
91 
92 template<typename T>
93 class optional;
94 
95 struct in_place_t
96 {
97 };
98 constexpr in_place_t in_place{};
99 
101 {
102 public:
103  constexpr explicit
105  {
106  }
107 };
108 constexpr nullopt_t nullopt{0};
109 
110 #if BOOST_VERSION >= 105600
111 using boost::bad_optional_access;
112 #else
113 class bad_optional_access : public std::logic_error
114 {
115 public:
117  : std::logic_error("bad optional access")
118  {
119  }
120 };
121 #endif
122 
123 template<typename T>
124 constexpr bool
125 operator==(const optional<T>& lhs, const optional<T>& rhs);
126 
127 template<typename T>
128 constexpr bool
129 operator!=(const optional<T>& lhs, const optional<T>& rhs);
130 
131 template<typename T>
132 constexpr bool
133 operator<(const optional<T>& lhs, const optional<T>& rhs);
134 
135 template<typename T>
136 constexpr bool
137 operator<=(const optional<T>& lhs, const optional<T>& rhs);
138 
139 template<typename T>
140 constexpr bool
141 operator>(const optional<T>& lhs, const optional<T>& rhs);
142 
143 template<typename T>
144 constexpr bool
145 operator>=(const optional<T>& lhs, const optional<T>& rhs);
146 
147 template<typename T>
148 class optional
149 {
150 public:
151  static_assert(!std::is_same<typename std::remove_cv<T>::type, in_place_t>::value &&
152  !std::is_same<typename std::remove_cv<T>::type, nullopt_t>::value &&
153  !std::is_reference<T>::value,
154  "Invalid instantiation of optional<T>");
155 
156  typedef T value_type;
157 
158  constexpr
159  optional() noexcept
160  {
161  }
162 
163  constexpr
164  optional(nullopt_t) noexcept
165  {
166  }
167 
168  constexpr
169  optional(const T& value)
170  : m_boostOptional(value)
171  {
172  }
173 
174  template<typename... Args>
175  constexpr explicit
176  optional(in_place_t, Args&&... args)
177  : m_boostOptional(boost::in_place<T>(std::forward<Args>(args)...))
178  {
179  }
180 
181  optional&
183  {
184  m_boostOptional = boost::none;
185  return *this;
186  }
187 
188  optional&
189  operator=(const optional& other)
190  {
191  m_boostOptional = other.m_boostOptional;
192  return *this;
193  }
194 
195  template<typename U,
196  typename = typename std::enable_if<std::is_same<typename std::decay<U>::type, T>::value>::type>
197  optional&
198  operator=(U&& value)
199  {
200  m_boostOptional = std::forward<U>(value);
201  return *this;
202  }
203 
204 public: // observers
205  constexpr const T*
206  operator->() const
207  {
208  return m_boostOptional.get_ptr();
209  }
210 
211  T*
213  {
214  return m_boostOptional.get_ptr();
215  }
216 
217  constexpr const T&
218  operator*() const
219  {
220  return m_boostOptional.get();
221  }
222 
223  T&
225  {
226  return m_boostOptional.get();
227  }
228 
229  constexpr explicit
230  operator bool() const noexcept
231  {
232  return static_cast<bool>(m_boostOptional);
233  }
234 
235  const T&
236  value() const
237  {
238  return const_cast<optional*>(this)->value();
239  }
240 
241  T&
243  {
244 #if BOOST_VERSION >= 105600
245  return m_boostOptional.value();
246 #else
247  if (!m_boostOptional) {
248  BOOST_THROW_EXCEPTION(bad_optional_access());
249  }
250  return m_boostOptional.get();
251 #endif
252  }
253 
254  template<typename U>
255  constexpr T
256  value_or(U&& default_value) const
257  {
258 #if BOOST_VERSION >= 105600
259  return m_boostOptional.value_or(default_value);
260 #else
261  return m_boostOptional.get_value_or(default_value);
262 #endif
263  }
264 
265 public: // modifiers
266  void
267  swap(optional& other)
268  {
269  boost::swap(m_boostOptional, other.m_boostOptional);
270  }
271 
272  template<typename... Args>
273  void
274  emplace(Args&&... args)
275  {
276  m_boostOptional = boost::in_place<T>(std::forward<Args>(args)...);
277  }
278 
279 private:
280  boost::optional<T> m_boostOptional;
281 
282  friend bool operator==<T>(const optional<T>&, const optional<T>&);
283  friend bool operator!=<T>(const optional<T>&, const optional<T>&);
284  friend bool operator< <T>(const optional<T>&, const optional<T>&);
285  friend bool operator<=<T>(const optional<T>&, const optional<T>&);
286  friend bool operator> <T>(const optional<T>&, const optional<T>&);
287  friend bool operator>=<T>(const optional<T>&, const optional<T>&);
288 };
289 
290 template<typename T>
291 constexpr bool
292 operator==(const optional<T>& lhs, const optional<T>& rhs)
293 {
294  return operator==(lhs.m_boostOptional, rhs.m_boostOptional);
295 }
296 
297 template<typename T>
298 constexpr bool
299 operator!=(const optional<T>& lhs, const optional<T>& rhs)
300 {
301  return operator!=(lhs.m_boostOptional, rhs.m_boostOptional);
302 }
303 
304 template<typename T>
305 constexpr bool
306 operator<(const optional<T>& lhs, const optional<T>& rhs)
307 {
308  return operator<(lhs.m_boostOptional, rhs.m_boostOptional);
309 }
310 
311 template<typename T>
312 constexpr bool
313 operator<=(const optional<T>& lhs, const optional<T>& rhs)
314 {
315  return operator<=(lhs.m_boostOptional, rhs.m_boostOptional);
316 }
317 
318 template<typename T>
319 constexpr bool
320 operator>(const optional<T>& lhs, const optional<T>& rhs)
321 {
322  return operator>(lhs.m_boostOptional, rhs.m_boostOptional);
323 }
324 
325 template<typename T>
326 constexpr bool
327 operator>=(const optional<T>& lhs, const optional<T>& rhs)
328 {
329  return operator>=(lhs.m_boostOptional, rhs.m_boostOptional);
330 }
331 
332 template<typename T>
334 make_optional(T&& value)
335 {
336  return optional<typename std::decay<T>::type>(std::forward<T>(value));
337 }
338 
339 template<typename T, typename... Args>
340 constexpr optional<T>
341 make_optional(Args&&... args)
342 {
343  return optional<T>(in_place, std::forward<Args>(args)...);
344 }
345 
346 } // namespace ndn
347 
348 #endif
349 #endif // NDN_UTIL_BACKPORTS_OPTIONAL_HPP
constexpr in_place_t in_place
constexpr nullopt_t nullopt
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
void swap(optional &other)
Definition: block.hpp:31
optional & operator=(const optional &other)
constexpr optional< T > make_optional(Args &&...args)
constexpr const T & operator*() const
constexpr nullopt_t(int)
STL namespace.
constexpr optional(const T &value)
bool operator<=(const Delegation &lhs, const Delegation &rhs)
Definition: delegation.cpp:43
optional & operator=(nullopt_t) noexcept
bool operator!=(const Data &lhs, const Data &rhs)
Definition: data.hpp:259
void emplace(Args &&...args)
constexpr optional() noexcept
constexpr T value_or(U &&default_value) const
const T & value() const
constexpr optional< typename std::decay< T >::type > make_optional(T &&value)
bool operator>(const Delegation &lhs, const Delegation &rhs)
Definition: delegation.hpp:54
bool operator>=(const Delegation &lhs, const Delegation &rhs)
Definition: delegation.hpp:60
bool operator==(const Data &lhs, const Data &rhs)
Definition: data.cpp:265
optional & operator=(U &&value)
constexpr optional(in_place_t, Args &&...args)
bool operator<(const Delegation &lhs, const Delegation &rhs)
Definition: delegation.cpp:36
constexpr const T * operator->() const
constexpr optional(nullopt_t) noexcept