YSTest: optional.h 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

optional.h
浏览该文件的文档.
1 /*
2 © 2015-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
33 #ifndef YB_INC_ystdex_optional_h_
34 #define YB_INC_ystdex_optional_h_ 1
35
36 #include "operators.hpp" // for nullptr_t, is_trivially_destructible, is_cv,
37 // std::move, empty_base, is_nothrow_moveable, and_, std::addressof,
38 // remove_cv_t, totally_ordered, or_, is_reference, is_same,
39 // is_nothrow_destructible, is_object, enable_if_t, is_constructible, decay_t,
40 // is_nothrow_swappable, ystdex::constfn_addressof, is_copyable;
41 #include <stdexcept> // for std::logic_error;
42 #include "placement.hpp" // for tagged_value;
43 #include <initializer_list> // for std::initializer_list;
44 #include "functional.hpp" // for default_last_value, std::accumulate;
45
46 namespace ystdex
47 {
48
50
51
53
55 yconstexpr const struct nullopt_t
56 {
61 yimpl(yconstfn
62 nullopt_t(nullptr_t)
63 {})
64 } nullopt{yimpl(nullptr)};
65
66 static_assert(std::is_literal_type<nullopt_t>(),
67 "Invalid implementation found.");
69
70
77 class YB_API bad_optional_access : public std::logic_error
78 {
79 public:
80 bad_optional_access()
81 : logic_error("bad optional access")
82 {}
83
84 ~bad_optional_access() override;
85 };
87
89
90 namespace details
91 {
92
93 template<typename _type, bool = std::is_trivially_destructible<_type>::value>
94 class optional_base : public optional_base<_type, true>
95 {
96 public:
98 using optional_base<_type, true>::optional_base;
99 ~optional_base()
100 {
101 if(this->has_value())
102 this->destroy_nothrow();
103 }
104
105 optional_base&
106 operator=(const optional_base& s)
107 {
108 return this->assign(s.value);
109 }
110 optional_base&
111 operator=(optional_base&& s)
112 {
113 return this->assign(std::move(s.value));
114 }
115 };
116
117 template<typename _type>
118 class optional_base<_type, true> : protected tagged_value<bool, _type>
119 {
120 // NOTE: See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15.
121 // Also http://wg21.cmeerw.net/cwg/issue1776.
122 static_assert(!is_cv<_type>(), "Cv-qualified type found.");
123
124 protected:
126 using base = tagged_value<bool, _type>;
127
129 using base::value;
130
131 public:
132 yconstfn
133 optional_base() = default;
134 template<typename... _tParams>
135 explicit yconstfn
136 optional_base(in_place_t, _tParams&&... args)
137 : base(true, in_place, yforward(args)...)
138 {}
139 optional_base(const optional_base& s)
140 : base(s)
141 {
142 if(has_value())
143 base::construct(s.value);
144 }
146 optional_base(optional_base&& s)
147 : base(s)
148 {
149 if(has_value())
150 base::construct(std::move(s.value));
151 }
156 ~optional_base() = default;
157
158 optional_base&
159 operator=(const optional_base& s)
160 {
161 return assign(s.value);
162 }
164 optional_base&
165 operator=(optional_base&& s) ynoexcept(is_nothrow_moveable<_type>())
166 {
167 return assign(std::move(s.value));
168 }
169
171 template<typename _tParam>
172 optional_base&
173 assign(_tParam&& arg) ynoexcept(and_<is_rvalue_reference<_tParam&&>,
174 is_nothrow_moveable<_type>>())
175 {
176 if(has_value() && arg.has_value())
177 value = yforward(arg);
178 else if(arg.has_value())
179 construct(yforward(arg));
180 else
181 reset();
182 return *this;
183 }
184
185 template<typename... _tParams>
186 void
187 construct(_tParams&&... args)
188 {
189 base::construct(yforward(args)...);
190 base::token = true;
191 }
192
193 void
194 destroy() ynothrow
195 {
196 base::token = {};
197 base::destroy_nothrow();
198 }
199
200 _type&
201 get() ynothrow
202 {
203 return value;
204 }
205
207 bool
208 has_value() const ynothrow
209 {
210 return base::token;
211 }
212
213 void
214 reset() ynothrow
215 {
216 if(has_value())
217 destroy();
218 }
219 };
220
221 } // namespace details;
222
223
232 template<typename _type>
233 class optional : private details::optional_base<remove_cv_t<_type>>, yimpl(
234 private totally_ordered<optional<_type>>, public totally_ordered<optional<
235 _type>, _type>, private totally_ordered<optional<_type>, nullopt_t>)
236 {
238 static_assert(!or_<is_reference<_type>, is_same<remove_cv_t<_type>,
239 in_place_t>, is_same<remove_cv_t<_type>, in_place_t>,
240 is_same<remove_cv_t<_type>, nullopt_t>>(),
241 "Invalid type found.");
243 static_assert(and_<is_nothrow_destructible<_type>, is_object<_type>>(),
244 "Invalid type found.");
245
246 public:
247 using value_type = _type;
248
249 private:
250 using base = details::optional_base<_type>;
251
252 public:
253 yconstfn
254 optional() ynothrow
255 {}
256 yconstfn
257 optional(nullopt_t) ynothrow
258 {}
259 yconstfn
260 optional(const _type& v)
261 : base(in_place, v)
262 {}
263 yconstfn
264 optional(_type&& v)
265 : base(in_place, std::move(v))
266 {}
267 template<typename... _tParams>
268 explicit yconstfn
269 optional(in_place_t, _tParams&&... args)
270 : base(in_place, yforward(args)...)
271 {}
272 template<typename _tOther, typename... _tParams,
273 yimpl(typename = enable_if_t<is_constructible<_type,
274 std::initializer_list<_tOther>&, _tParams&&...>::value>)>
275 explicit yconstfn
276 optional(in_place_t, std::initializer_list<_tOther> il, _tParams&&... args)
277 : base(in_place, il, yforward(args)...)
278 {}
279 optional(const optional&) yimpl(= default);
280 optional(optional&&) ynoexcept(is_nothrow_move_constructible<_type>())
281 yimpl(= default);
282 ~optional() yimpl(= default);
283
284 optional&
285 operator=(nullopt_t) ynothrow
286 {
287 reset();
288 return *this;
289 }
290 optional&
291 operator=(const optional& o)
292 {
293 get_base() = o.get_base();
294 return *this;
295 }
297 optional&
298 operator=(optional&& o) ynoexcept(is_nothrow_moveable<_type>())
299 {
300 get_base() = std::move(o.get_base());
301 return *this;
302 }
303 template<typename _tOther>
304 yimpl(enable_if_t)<is_same<decay_t<_tOther>, _type>::value, optional&>
305 operator=(_tOther&& v)
306 {
307 if(has_value())
308 this->get() = yforward(v);
309 else
310 this->construct(yforward(v));
311 return *this;
312 }
313
314 template<typename... _tParams>
315 void
316 emplace(_tParams&&... args)
317 {
318 reset();
319 this->construct(yforward(args)...);
320 }
321 template<typename _tOther, typename... _tParams>
322 void
323 emplace(std::initializer_list<_tOther> il, _tParams&&... args)
324 {
325 reset();
326 this->construct(il, yforward(args)...);
327 }
328
329 private:
330 base&
331 get_base() ynothrow
332 {
333 return static_cast< base&>(*this);
334 }
335 const base&
336 get_base() const ynothrow
337 {
338 return static_cast<const base&>(*this);
339 }
340
341 public:
342 void
343 swap(optional& o) ynoexcept(and_<is_nothrow_move_constructible<value_type>,
344 is_nothrow_swappable<value_type>>())
345 {
346 using std::swap;
347
348 if(has_value() && o.has_value())
349 swap(this->get(), o.get());
350 else if(has_value())
351 {
352 o.construct(std::move(this->get()));
353 this->destroy();
354 }
355 else if(o.has_value())
356 {
357 this->construct(std::move(this->get()));
358 o.destroy();
359 }
360 }
361
362 yconstfn_relaxed _type*
363 operator->()
364 {
365 return std::addressof(this->get());
366 }
367 yconstfn const _type*
368 operator->() const
369 {
370 return ystdex::constfn_addressof(this->get());
371 }
372
373 yconstfn_relaxed _type&
374 operator*() &
375 {
376 return this->get();
377 }
378 yconstfn const _type&
379 operator*() const&
380 {
381 return this->get();
382 }
384 yconstfn_relaxed _type&&
385 operator*() &&
386 {
387 return std::move(this->get());
388 }
390 yconstfn _type&&
391 operator*() const&&
392 {
393 return std::move(this->get());
394 }
395
396 explicit yconstfn
397 operator bool() const ynothrow
398 {
399 return has_value();
400 }
401
403 using base::has_value;
404
405 yconstfn_relaxed _type&
406 value() &
407 {
408 return has_value() ? this->get()
409 : (throw bad_optional_access(), this->get());
410 }
411 yconstfn const _type&
412 value() const&
413 {
414 return has_value() ? this->get()
415 : (throw bad_optional_access(), this->get());
416 }
418 yconstfn_relaxed _type&&
419 value() &&
420 {
421 return has_value() ? std::move(this->get())
422 : (throw bad_optional_access(), std::move(this->get()));
423 }
425 yconstfn _type&&
426 value() const&&
427 {
428 return has_value() ? std::move(this->get())
429 : (throw bad_optional_access(), std::move(this->get()));
430 }
431
432 template<typename _tOther>
433 yconstfn _type
434 value_or(_tOther&& other) const&
435 {
436 static_assert(is_copyable<_type>(), "Invalid type found.");
437
438 return has_value() ? this->get() : static_cast<_type>(yforward(other));
439 }
440 template<typename _tOther>
441 yconstfn_relaxed _type
442 value_or(_tOther&& other) &&
443 {
444 static_assert(is_copyable<_type>(), "Invalid type found.");
445
446 return has_value() ? std::move(this->get())
447 : static_cast<_type>(yforward(other));
448 }
449
451 using base::reset;
452 };
453
455
456
464 template<typename _type>
465 yconstfn bool
466 operator==(const optional<_type>& x, const optional<_type>& y)
467 {
468 return bool(x) == bool(y) && (!x || *x == *y);
469 }
470 template<typename _type>
471 yconstfn bool
472 operator==(const optional<_type>& x, nullopt_t) ynothrow
473 {
474 return !x;
475 }
476 template<typename _type>
477 yconstfn bool
478 operator==(const optional<_type>& x, const _type& v)
479 {
480 return bool(x) ? *x == v : false;
481 }
482
483 template<typename _type>
484 yconstfn bool
485 operator<(const optional<_type>& x, const optional<_type>& y)
486 {
487 return bool(y) && (!x || *x < *y);
488 }
490
492
493 template<typename _type> void
494 swap(optional<_type>& x, optional<_type>& y) ynoexcept_spec(x.swap(y))
495 {
496 return x.swap(y);
497 }
498
506 template<typename _type, typename... _tParams>
507 optional<_type>
508 make_optional(_tParams&&... args)
509 {
510 return optional<_type>(in_place, yforward(args)...);
511 }
512 template<typename _type, typename _tOther, typename... _tParams>
513 optional<_type>
514 make_optional(std::initializer_list<_tOther> il, _tParams&&... args)
515 {
516 return optional<_type>(in_place, il, yforward(args)...);
517 }
519
520
526 template<typename _type, typename... _tParams>
528 yconstfn optional<_type>
529 make_optional_inplace(_tParams&&... args)
530 {
531 return optional<_type>(in_place, yforward(args)...);
532 }
533
539 template<typename _type>
540 yconstfn _type&
541 ref_opt(optional<_type>&& o) ynothrowv
542 {
543 return *o.operator->();
544 }
545 template<typename _type>
546 yconstfn _type&
547 ref_opt() ynothrowv
548 {
549 return ref_opt(make_optional_inplace<_type>());
550 }
552
553
561 template<typename _type>
562 struct optional_last_value
563 {
564 template<typename _tIn>
565 optional<_type>
566 operator()(_tIn first, _tIn last) const
567 {
568 return std::accumulate(first, last, optional<_type>(),
569 [](optional<_type>&, decltype(*first) val){
570 return yforward(val);
571 });
572 }
573 };
574
575 template<>
576 struct optional_last_value<void> : default_last_value<void>
577 {};
579
580
581 } // namespace ystdex;
582
583
584 namespace std
585 {
586
593 template<typename>
594 struct hash;
595
596 template<typename _type>
597 struct hash<ystdex::optional<_type>>
598 {
599 size_t
600 operator()(const ystdex::optional<_type>& k) const
601 yimpl(ynoexcept_spec(hash<_type>{}(*k)))
602 {
603 // NOTE: The unspecified value is randomly picked.
604 return k ? hash<_type>{}(*k) : yimpl(-4242);
605 }
606 };
608
609 } // namespace std;
610
611 #endif
612
ystdex::optional::operator*
_type && operator*() const &&
Definition: optional.h:391
ystdex::optional::operator*
_type && operator*()&&
Definition: optional.h:385
ystdex::reset
bool reset(std::unique_ptr< _type, _tDeleter > &p)
Definition: memory.hpp:708
ystdex::optional::operator=
enable_if_t< is_same< decay_t< _tOther >, _type >::value, optional & > operator=(_tOther &&v)
Definition: optional.h:305
ystdex::make_optional_inplace
optional< _type > make_optional_inplace(_tParams &&...args)
使用指定参数构造指定 optional 实例的值。
Definition: optional.h:529
yconstfn
#define yconstfn
指定编译时常量函数。
Definition: ydef.h:680
ystdex::constfn_addressof
enable_if_t<!has_overloaded_addressof< _type >::value, _type * > constfn_addressof(_type &r)
尝试对非重载 operator& 提供 constexpr 的 std::addressof 替代。
Definition: addressof.hpp:78
v
byte v
Definition: CharRenderer.cpp:75
ystdex::swap
void swap(optional< _type > &x, optional< _type > &y)
Definition: optional.h:494
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
NPL::x
const TermNode &term ynothrow const TermNode &term ynothrow const TermNode &term ynothrow TermNode &term const TermNode &term ValueNode &node const ValueNode &node const _type & x
Definition: SContext.h:94
ystdex::details::optional_base< _type, true >::operator=
optional_base & operator=(optional_base &&s)
Definition: optional.h:165
ystdex::optional::value_or
_type value_or(_tOther &&other)&&
Definition: optional.h:442
ystdex::or_
Definition: type_traits.hpp:438
ystdex::details::optional_base< _type, true >::reset
void reset()
Definition: optional.h:214
ynoexcept_spec
#define ynoexcept_spec(...)
表达式 noexcept 异常规范。
Definition: ydef.h:794
platform::bool
std::FILE *fp bool
Definition: FileIO.h:1280
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:262
ystdex::details::optional_base::operator=
optional_base & operator=(const optional_base &s)
Definition: optional.h:106
yconstfn_relaxed
#define yconstfn_relaxed
指定编译时没有 C++11 限制和隐式成员 const 的常量函数。
Definition: ydef.h:692
ystdex::details::optional_base< _type, true >::operator=
optional_base & operator=(const optional_base &s)
Definition: optional.h:159
ystdex::is_nothrow_moveable
Definition: type_traits.hpp:935
ystdex::is_cv
判断指定类型是否为 const 或 volatile 类型。
Definition: type_traits.hpp:882
ystdex::cpp2014::enable_if_t
typename enable_if< _bCond, _type >::type enable_if_t
Definition: type_traits.hpp:343
ystdex::any_ops::construct
any_manager construct(any_storage &storage, _tParams &&...args)
使用指定处理器初始化存储。
Definition: any.h:257
CHRLib::args
_tParams && args
Definition: CharacterProcessing.h:538
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:679
ystdex::nullopt_t
无值状态指示。
Definition: optional.h:55
ystdex::optional_last_value
合并可选值序列。
Definition: optional.h:562
ystdex::optional::optional
optional(nullopt_t)
Definition: optional.h:257
ystdex::optional_last_value::operator()
optional< _type > operator()(_tIn first, _tIn last) const
Definition: optional.h:566
ystdex::optional::value_type
_type value_type
Definition: optional.h:247
ystdex::tagged_value
带记号标记的可选值。
Definition: placement.hpp:523
ystdex::details::optional_base< _type, true >::assign
optional_base & assign(_tParam &&arg)
Definition: optional.h:173
ystdex::in_place_t
in_place_tag(&)(empty_base<>) in_place_t
原地空标记类型。
Definition: placement.hpp:69
ystdex::nullopt_t::nullopt_t
nullopt_t(nullptr_t)
Definition: optional.h:63
ystdex::optional::value
_type && value()&&
Definition: optional.h:419
ystdex::optional::optional
optional(in_place_t, _tParams &&...args)
Definition: optional.h:269
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:766
ystdex::optional::value
const _type & value() const &
Definition: optional.h:412
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
ystdex::details::optional_base< _type, true >::optional_base
optional_base(optional_base &&s)
Definition: optional.h:146
ystdex
特性测试宏。
Definition: ydef.h:822
std::hash
ystdex::observer_ptr 散列支持。
Definition: memory.hpp:1193
ystdex::operator==
bool operator==(nullptr_t lhs, const _type &rhs)
Definition: ydef.h:895
ystdex::details::optional_base< _type, true >::construct
void construct(_tParams &&...args)
Definition: optional.h:187
ystdex::optional::operator*
_type & operator*()&
Definition: optional.h:374
ystdex::optional::value
_type & value()&
Definition: optional.h:406
ystdex::optional::operator->
const _type * operator->() const
Definition: optional.h:368
ystdex::optional::swap
void swap(optional &o)
Definition: optional.h:343
ystdex::in_place
in_place_tag in_place(empty_base<>)
原地标记函数。
Definition: placement.hpp:85
ystdex::optional::operator=
optional & operator=(optional &&o)
Definition: optional.h:298
functional.hpp
函数和可调用对象。
ystdex::details::optional_base::~optional_base
~optional_base()
Definition: optional.h:99
ystdex::default_last_value
合并值序列。
Definition: functional.hpp:1217
ystdex::assign
void assign(_tCon &con, _tParams &&...args)
插入参数指定的元素到容器。
Definition: container.hpp:413
ystdex::make_optional
optional< _type > make_optional(_tParams &&...args)
创建 optional 对象。
Definition: optional.h:508
ystdex::details::optional_base< _type, true >::optional_base
optional_base(const optional_base &s)
Definition: optional.h:139
ystdex::is_nothrow_swappable
Definition: type_traits.hpp:555
std::hash< ystdex::optional< _type > >::operator()
size_t operator()(const ystdex::optional< _type > &k) const
Definition: optional.h:600
ystdex::optional::optional
optional()
Definition: optional.h:254
operators.hpp
重载操作符。
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:786
ystdex::details::optional_base
Definition: optional.h:94
ystdex::optional::value
_type && value() const &&
Definition: optional.h:426
CHRLib::CharSet::other
Definition: Encoding.h:65
ystdex::nullptr_t
空指针类。
Definition: ydef.h:861
ystdex::swap
void swap(container_adaptor< _tSeqCon > &x, container_adaptor< _tSeqCon > &y)
Definition: container.hpp:179
ystdex::optional::value_or
_type value_or(_tOther &&other) const &
Definition: optional.h:434
ystdex::details::optional_base< _type, true >::has_value
bool has_value() const
Definition: optional.h:208
ystdex::destroy
void destroy(_tFwd first, _tFwd last)
Definition: placement.hpp:235
std
Definition: memory.hpp:1183
placement.hpp
放置对象管理操作。
ystdex::optional::optional
optional(in_place_t, std::initializer_list< _tOther > il, _tParams &&...args)
Definition: optional.h:276
ystdex::optional::emplace
void emplace(_tParams &&...args)
Definition: optional.h:316
ystdex::optional::optional
optional(const _type &v)
Definition: optional.h:260
ystdex::details::optional_base::operator=
optional_base & operator=(optional_base &&s)
Definition: optional.h:111
ystdex::construct
void construct(_tIter i, _tParams &&...args)
使用指定参数在迭代器指定的位置以指定参数初始化构造对象。
Definition: placement.hpp:178
yforward
#define yforward(_expr)
根据参数类型使用 std::forward 传递对应参数。
Definition: ydef.h:995
ystdex::details::optional_base< _type, true >::destroy
void destroy()
Definition: optional.h:194
ystdex::optional::operator->
_type * operator->()
Definition: optional.h:363
YB_API
#define YB_API
YBase 应用程序编程接口：用于向库文件约定链接。
Definition: ydef.h:592
ystdex::optional
可选值对象包装。
Definition: optional.h:233
ystdex::optional::operator*
const _type & operator*() const &
Definition: optional.h:379
ystdex::bad_optional_access
可选值操作失败异常。
Definition: optional.h:77
ystdex::ref_opt
_type & ref_opt(optional< _type > &&o)
从 optional 实例的临时对象取左值引用。
Definition: optional.h:541
ystdex::optional::get_base
base & get_base()
Definition: optional.h:331
ystdex::optional::emplace
void emplace(std::initializer_list< _tOther > il, _tParams &&...args)
Definition: optional.h:323
ystdex::and_
逻辑操作元函数。
Definition: type_traits.hpp:420
ystdex::optional::optional
optional(_type &&v)
Definition: optional.h:264
ystdex::is_copyable
Definition: type_traits.hpp:917
ystdex::bad_optional_access::bad_optional_access
bad_optional_access()
Definition: optional.h:80
ystdex::optional::operator=
optional & operator=(const optional &o)
Definition: optional.h:291
ystdex::details::optional_base< _type, true >::optional_base
optional_base(in_place_t, _tParams &&...args)
Definition: optional.h:136
ynoexcept
#define ynoexcept(...)
YSLib 无异常抛出保证：指定特定的异常规范。
Definition: ydef.h:746
ystdex::optional::get_base
const base & get_base() const
Definition: optional.h:336