YSTest: optional.h 源文件

YSTest PreAlpha_b700_20160611 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 is_trivially_destructible, is_cv, std::move,
37 // empty_base, is_nothrow_moveable, and_, std::addressof, remove_cv_t,
38 // totally_ordered, or_, is_reference, is_same, is_nothrow_destructible,
39 // is_object, enable_if_t, is_constructible, decay_t, is_nothrow_swappable,
40 // ystdex::constfn_addressof, is_copyable
41 #include <stdexcept> // for std::logic_error;
42 #include <new> // for placement ::operator new from standard library;
43 #include <initializer_list> // for std::initializer_list;
44 #include "functional.hpp" // for default_last_value, std::accumulate;
45 #include "memory.hpp" // for ystdex::construct_in, ystdex::destruct_in;
46
47 namespace ystdex
48 {
49
51
52
56 yconstexpr const struct in_place_t{} in_place{};
57
58
60
61
63 yconstexpr const struct nullopt_t
64 {
65 yimpl()
66 } nullopt{yimpl()};
67
68 static_assert(std::is_literal_type<nullopt_t>(),
69 "Invalid implementation found.");
71
72
79 class YB_API bad_optional_access : public std::logic_error
80 {
81 public:
82 bad_optional_access()
83 : logic_error("bad optional access")
84 {}
85
86 ~bad_optional_access() override;
87 };
89
91
92 namespace details
93 {
94
95 template<typename _type, bool = std::is_trivially_destructible<_type>::value>
96 class optional_base : public optional_base<_type, true>
97 {
98 public:
100 using optional_base<_type, true>::optional_base;
101 ~optional_base()
102 {
103 if(this->engaged)
104 this->destroy_raw();
105 }
106
107 optional_base&
108 operator=(const optional_base& s)
109 {
110 return this->assign(s.value);
111 }
112 optional_base&
113 operator=(optional_base&& s)
114 {
115 return this->assign(std::move(s.value));
116 }
117 };
118
119 template<typename _type>
120 class optional_base<_type, true>
121 {
122 // NOTE: See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15.
123 // Also http://wg21.cmeerw.net/cwg/issue1776.
124 static_assert(!is_cv<_type>(), "Cv-qualified type found.");
125
126 protected:
127 union
128 {
129 empty_base<> empty;
130 mutable _type value;
131 };
132 bool engaged = {};
133
134 public:
135 yconstfn
136 optional_base() ynothrow
137 : empty()
138 {}
139 template<typename... _tParams>
140 explicit yconstfn
141 optional_base(in_place_t, _tParams&&... args)
142 : value(yforward(args)...), engaged(true)
143 {}
144 optional_base(const optional_base& s)
145 : engaged(s.engaged)
146 {
147 if(engaged)
148 construct_raw(s.value);
149 }
150 optional_base(const optional_base&& s)
151 ynoexcept_spec(is_nothrow_move_constructible<_type>())
152 : engaged(s.engaged)
153 {
154 if(engaged)
155 construct_raw(std::move(s.value));
156 }
162 ~optional_base()
163 {}
164
165 optional_base&
166 operator=(const optional_base& s)
167 {
168 return assign(s.value);
169 }
171 optional_base&
172 operator=(optional_base&& s) ynoexcept(is_nothrow_moveable<_type>())
173 {
174 return assign(std::move(s.value));
175 }
176
178 template<typename _tParam>
179 optional_base&
180 assign(_tParam&& arg) ynoexcept(and_<is_rvalue_reference<_tParam&&>,
181 is_nothrow_moveable<_type>>())
182 {
183 if(engaged && arg.engaged)
184 value = yforward(arg);
185 else if(arg.engaged)
186 construct(yforward(arg));
187 else
188 reset();
189 return *this;
190 }
191
192 template<typename... _tParams>
193 void
194 construct(_tParams&&... args)
195 {
196 construct_raw(yforward(args)...);
197 engaged = true;
198 }
199
200 private:
201 template<typename... _tParams>
202 void
203 construct_raw(_tParams&&... args)
204 {
205 ystdex::construct_in(value, yforward(args)...);
206 }
207
208 public:
209 void
210 destroy() ynothrow
211 {
212 engaged = {};
213 destroy_raw();
214 }
215
216 protected:
217 void
218 destroy_raw() ynothrow
219 {
220 ynoexcept_assert("Invalid type found.", value.~type());
221
222 ystdex::destruct_in(value);
223 }
224
225 public:
226 _type&
227 get() ynothrow
228 {
229 return value;
230 }
231
232 bool
233 is_engaged() const ynothrow
234 {
235 return engaged;
236 }
237
238 void
239 reset() ynothrow
240 {
241 if(engaged)
242 destroy();
243 }
244 };
245
246 } // namespace details;
247
248
257 template<typename _type>
258 class optional : private details::optional_base<remove_cv_t<_type>>, yimpl(
259 private totally_ordered<optional<_type>>, public totally_ordered<optional<
260 _type>, _type>, private totally_ordered<optional<_type>, nullopt_t>)
261 {
263 static_assert(!or_<is_reference<_type>, is_same<remove_cv_t<_type>,
264 in_place_t>, is_same<remove_cv_t<_type>, nullopt_t>>(),
265 "Invalid type found.");
267 static_assert(and_<is_nothrow_destructible<_type>, is_object<_type>>(),
268 "Invalid type found.");
269
270 public:
271 using value_type = _type;
272
273 private:
274 using base = details::optional_base<_type>;
275
276 public:
277 yconstfn
278 optional() ynothrow
279 {}
280 yconstfn
281 optional(nullopt_t) ynothrow
282 {}
283 yconstfn
284 optional(const _type& v)
285 : base(in_place, v)
286 {}
287 yconstfn
288 optional(_type&& v)
289 : base(in_place, std::move(v))
290 {}
291 template<typename... _tParams>
292 explicit yconstfn
293 optional(in_place_t, _tParams&&... args)
294 : base(in_place, yforward(args)...)
295 {}
296 template<typename _tOther, typename... _tParams,
297 yimpl(typename = enable_if_t<is_constructible<_type,
298 std::initializer_list<_tOther>&, _tParams&&...>::value>)>
299 explicit yconstfn
300 optional(in_place_t, std::initializer_list<_tOther> il, _tParams&&... args)
301 : base(in_place, il, yforward(args)...)
302 {}
303 optional(const optional&) yimpl(= default);
304 optional(optional&&) ynoexcept(is_nothrow_move_constructible<_type>())
305 yimpl(= default);
306 ~optional() yimpl(= default);
307
308 optional&
309 operator=(nullopt_t) ynothrow
310 {
311 this->reset();
312 return *this;
313 }
314 optional&
315 operator=(const optional& o)
316 {
317 get_base() = o.get_base();
318 return *this;
319 }
321 optional&
322 operator=(optional&& o) ynoexcept(is_nothrow_moveable<_type>())
323 {
324 get_base() = std::move(o.get_base());
325 return *this;
326 }
327 template<typename _tOther>
328 yimpl(enable_if_t)<is_same<decay_t<_tOther>, _type>::value, optional&>
329 operator=(_tOther&& v)
330 {
331 if(this->is_engaged())
332 this->get() = yforward(v);
333 else
334 this->construct(yforward(v));
335 return *this;
336 }
337
338 template<typename... _tParams>
339 void
340 emplace(_tParams&&... args)
341 {
342 this->reset();
343 this->construct(yforward(args)...);
344 }
345 template<typename _tOther, typename... _tParams>
346 void
347 emplace(std::initializer_list<_tOther> il, _tParams&&... args)
348 {
349 this->reset();
350 this->construct(il, yforward(args)...);
351 }
352
353 private:
354 base&
355 get_base() ynothrow
356 {
357 return static_cast< base&>(*this);
358 }
359 const base&
360 get_base() const ynothrow
361 {
362 return static_cast<const base&>(*this);
363 }
364
365 public:
366 void
367 swap(optional& o) ynoexcept(and_<is_nothrow_move_constructible<value_type>,
368 is_nothrow_swappable<value_type>>())
369 {
370 using std::swap;
371
372 if(this->is_engaged() && o.is_engaged())
373 swap(this->get(), o.get());
374 else if(this->is_engaged())
375 {
376 o.construct(std::move(this->get()));
377 this->destroy();
378 }
379 else if(o.is_engaged())
380 {
381 this->construct(std::move(this->get()));
382 o.destroy();
383 }
384 }
385
386 yconstfn_relaxed _type*
387 operator->()
388 {
389 return std::addressof(this->get());
390 }
391 yconstfn const _type*
392 operator->() const
393 {
394 return ystdex::constfn_addressof(this->get());
395 }
396
397 yconstfn_relaxed _type&
398 operator*() &
399 {
400 return this->get();
401 }
402 yconstfn const _type&
403 operator*() const&
404 {
405 return this->get();
406 }
408 yconstfn_relaxed _type&&
409 operator*() &&
410 {
411 return std::move(this->get());
412 }
414 yconstfn _type&&
415 operator*() const&&
416 {
417 return std::move(this->get());
418 }
419
420 explicit yconstfn
421 operator bool() const ynothrow
422 {
423 return this->is_engaged();
424 }
425
426 yconstfn_relaxed _type&
427 value() &
428 {
429 return this->is_engaged() ? this->get() : (throw bad_optional_access(),
430 this->get());
431 }
432 yconstfn const _type&
433 value() const&
434 {
435 return this->is_engaged() ? this->get() : (throw bad_optional_access(),
436 this->get());
437 }
439 yconstfn_relaxed _type&&
440 value() &&
441 {
442 return this->is_engaged() ? std::move(this->get())
443 : (throw bad_optional_access(), std::move(this->get()));
444 }
446 yconstfn _type&&
447 value() const&&
448 {
449 return this->is_engaged() ? std::move(this->get())
450 : (throw bad_optional_access(), std::move(this->get()));
451 }
452
453 template<typename _tOther>
454 yconstfn _type
455 value_or(_tOther&& other) const&
456 {
457 static_assert(is_copyable<_type>(), "Invalid type found.");
458
459 return this->is_engaged() ? this->get()
460 : static_cast<_type>(yforward(other));
461 }
462 template<typename _tOther>
463 yconstfn_relaxed _type
464 value_or(_tOther&& other) &&
465 {
466 static_assert(is_copyable<_type>(), "Invalid type found.");
467
468 return this->is_engaged() ? std::move(this->get())
469 : static_cast<_type>(yforward(other));
470 }
471 };
472
474
475
483 template<typename _type>
484 yconstfn bool
485 operator==(const optional<_type>& x, const optional<_type>& y)
486 {
487 return bool(x) == bool(y) && (!x || *x == *y);
488 }
489 template<typename _type>
490 yconstfn bool
491 operator==(const optional<_type>& x, nullopt_t) ynothrow
492 {
493 return !x;
494 }
495 template<typename _type>
496 yconstfn bool
497 operator==(const optional<_type>& x, const _type& v)
498 {
499 return bool(x) ? *x == v : false;
500 }
501
502 template<typename _type>
503 yconstfn bool
504 operator<(const optional<_type>& x, const optional<_type>& y)
505 {
506 return bool(y) && (!x || *x < *y);
507 }
509
511
512 template<typename _type> void
513 swap(optional<_type>& x, optional<_type>& y) ynoexcept_spec(x.swap(y))
514 {
515 return x.swap(y);
516 }
517 template<typename _type>
518 yconstfn optional<decay_t<_type>>
519 make_optional(_type&& v)
520 {
521 return optional<decay_t<_type>>(yforward(v));
522 }
524
530 template<typename _type, typename... _tParams>
532 yconstfn optional<_type>
533 make_optional_inplace(_tParams&&... args)
534 {
535 return optional<_type>(in_place, yforward(args)...);
536 }
537
543 template<typename _type>
544 yconstfn _type&
545 ref_opt(optional<_type>&& o) ynothrowv
546 {
547 return *o.operator->();
548 }
549 template<typename _type>
550 yconstfn _type&
551 ref_opt() ynothrowv
552 {
553 return ref_opt(make_optional_inplace<_type>());
554 }
556
557
565 template<typename _type>
566 struct optional_last_value
567 {
568 template<typename _tIn>
569 optional<_type>
570 operator()(_tIn first, _tIn last) const
571 {
572 return std::accumulate(first, last, optional<_type>(),
573 [](optional<_type>&, decltype(*first) val){
574 return yforward(val);
575 });
576 }
577 };
578
579 template<>
580 struct optional_last_value<void> : default_last_value<void>
581 {};
583
584
585 } // namespace ystdex;
586
587
588 namespace std
589 {
590
597 template<typename>
598 struct hash;
599
600 template<typename _type>
601 struct hash<ystdex::optional<_type>>
602 {
603 size_t
604 operator()(const ystdex::optional<_type>& k) const
605 yimpl(ynoexcept_spec(hash<_type>{}(*k)))
606 {
607 // NOTE: The unspecified value is randomly picked.
608 return k ? hash<_type>{}(*k) : yimpl(-4242);
609 }
610 };
612
613 } // namespace std;
614
615 #endif
616
ystdex::optional::operator=
enable_if_t< is_same< decay_t< _tOther >, _type >::value, optional & > operator=(_tOther &&v)
Definition: optional.h:329
ystdex::make_optional
optional< decay_t< _type > > make_optional(_type &&v)
Definition: optional.h:519
ystdex::operator==
bool operator==(nullptr_t lhs, const _type &rhs)
Definition: ydef.h:869
YSLib::Drawing::x
The boundary is out of the const Rect SDst SPos x
Definition: YDraw.h:127
yconstexpr
#define yconstexpr
指定编译时常量表达式。
Definition: ydef.h:653
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:740
ystdex::details::optional_base< _type, true >::reset
void reset()
Definition: optional.h:239
ystdex::swap
void swap(optional< _type > &x, optional< _type > &y)
Definition: optional.h:513
ystdex::bad_optional_access::bad_optional_access
bad_optional_access()
Definition: optional.h:82
ystdex::default_last_value
合并值序列。
Definition: functional.hpp:1084
ystdex::swap
void swap(container_adaptor< _tSeqCon > &x, container_adaptor< _tSeqCon > &y)
Definition: container.hpp:179
v
byte v
Definition: CharRenderer.cpp:75
ystdex::details::optional_base::~optional_base
~optional_base()
Definition: optional.h:101
ystdex::make_optional_inplace
optional< _type > make_optional_inplace(_tParams &&...args)
使用指定参数构造指定 optional 实例的值。
Definition: optional.h:533
ystdex::optional::optional
optional(_type &&v)
Definition: optional.h:288
ystdex::cpp2014::enable_if_t
typename enable_if< _bCond, _type >::type enable_if_t
Definition: type_traits.hpp:350
ystdex::optional::value
_type && value()&&
Definition: optional.h:440
ystdex::in_place_t
原地构造标记。
Definition: optional.h:56
ystdex::optional_last_value
合并可选值序列。
Definition: optional.h:566
ystdex::details::optional_base::operator=
optional_base & operator=(optional_base &&s)
Definition: optional.h:113
ystdex::optional::value
const _type & value() const &
Definition: optional.h:433
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:760
ystdex::nullopt
const struct ystdex::nullopt_t nullopt
ystdex::reset
bool reset(std::unique_ptr< _type > &p)
Definition: memory.hpp:584
ystdex::details::optional_base< _type, true >::empty
empty_base empty
Definition: optional.h:129
ystdex::nullopt_t
无值状态指示。
Definition: optional.h:63
ystdex::details::optional_base
Definition: optional.h:96
ystdex::optional::optional
optional(nullopt_t)
Definition: optional.h:281
ystdex::is_nothrow_swappable
Definition: type_traits.hpp:530
ystdex::ref_opt
_type & ref_opt(optional< _type > &&o)
从 optional 实例的临时对象取左值引用。
Definition: optional.h:545
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:256
YB_API
#define YB_API
YBase 应用程序编程接口：用于向库文件约定链接。
Definition: ydef.h:566
ystdex::assign
void assign(_tCon &con, _tParams &&...args)
插入参数指定的元素到容器。
Definition: container.hpp:412
ystdex::optional::value_type
_type value_type
Definition: optional.h:271
ystdex::construct
void construct(_tIter i, _tParams &&...args)
使用指定参数在迭代器指定的位置构造对象。
Definition: memory.hpp:189
ynoexcept_spec
#define ynoexcept_spec(...)
表达式 noexcept 异常规范。
Definition: ydef.h:768
ystdex::in_place
const struct ystdex::in_place_t in_place
ystdex::constfn_addressof
enable_if_t<!has_overloaded_addressof< _type >::value, _type * > constfn_addressof(_type &r)
尝试对非重载 operator& 提供 constexpr 的 std::addressof 替代。
Definition: addressof.hpp:78
ystdex::construct_in
void construct_in(_type &obj, _tParams &&...args)
原地构造。
Definition: memory.hpp:164
ystdex::optional::value_or
_type value_or(_tOther &&other)&&
Definition: optional.h:464
ynoexcept_assert
#define ynoexcept_assert(_msg,...)
表达式 noexcept 静态断言。
Definition: ydef.h:721
ystdex::details::optional_base< _type, true >::value
_type value
Definition: optional.h:130
functional.hpp
函数和可调用对象。
yconstfn_relaxed
#define yconstfn_relaxed
指定编译时没有 C++11 限制和隐式成员 const 的常量函数。
Definition: ydef.h:666
std
Definition: memory.hpp:1100
ystdex::optional::value
_type & value()&
Definition: optional.h:427
ystdex::optional::operator->
const _type * operator->() const
Definition: optional.h:392
ystdex::any_ops::destroy
Definition: any.h:254
ystdex::details::optional_base< _type, true >::assign
optional_base & assign(_tParam &&arg)
Definition: optional.h:180
std::hash
ystdex::observer_ptr 散列支持。
Definition: memory.hpp:1110
ystdex::optional::operator=
optional & operator=(optional &&o)
Definition: optional.h:322
ystdex::details::optional_base< _type, true >::construct
void construct(_tParams &&...args)
Definition: optional.h:194
ystdex
特性测试宏。
Definition: ydef.h:796
ystdex::details::optional_base< _type, true >::destroy_raw
void destroy_raw()
Definition: optional.h:218
memory.hpp
存储和智能指针特性。
ystdex::optional_last_value::operator()
optional< _type > operator()(_tIn first, _tIn last) const
Definition: optional.h:570
ystdex::optional::operator->
_type * operator->()
Definition: optional.h:387
ystdex::details::optional_base< _type, true >::operator=
optional_base & operator=(optional_base &&s)
Definition: optional.h:172
ystdex::optional::get_base
base & get_base()
Definition: optional.h:355
YSLib::UI::y
SPos SPos y
Definition: YWidget.cpp:44
ystdex::destruct_in
void destruct_in(_type &obj)
原地析构。
Definition: memory.hpp:218
ystdex::optional::emplace
void emplace(_tParams &&...args)
Definition: optional.h:340
ystdex::optional::optional
optional(in_place_t, _tParams &&...args)
Definition: optional.h:293
ystdex::optional::value
_type && value() const &&
Definition: optional.h:447
ystdex::empty_base
空基类模板。
Definition: ydef.h:902
operators.hpp
重载操作符。
ystdex::optional::optional
optional(const _type &v)
Definition: optional.h:284
ynoexcept
#define ynoexcept(...)
YSLib 无异常抛出保证：指定特定的异常规范。
Definition: ydef.h:720
ystdex::details::optional_base< _type, true >::optional_base
optional_base()
Definition: optional.h:136
ystdex::optional::get_base
const base & get_base() const
Definition: optional.h:360
std::hash< ystdex::optional< _type > >::operator()
size_t operator()(const ystdex::optional< _type > &k) const
Definition: optional.h:604
yconstfn
#define yconstfn
指定编译时常量函数。
Definition: ydef.h:654
ystdex::details::optional_base< _type, true >::construct_raw
void construct_raw(_tParams &&...args)
Definition: optional.h:203
ystdex::details::optional_base< _type, true >::destroy
void destroy()
Definition: optional.h:210
ystdex::optional
可选值对象包装。
Definition: optional.h:258
ystdex::optional::optional
optional(in_place_t, std::initializer_list< _tOther > il, _tParams &&...args)
Definition: optional.h:300
ystdex::optional::operator*
_type & operator*()&
Definition: optional.h:398
ystdex::optional::swap
void swap(optional &o)
Definition: optional.h:367
CHRLib::CharSet::other
Definition: Encoding.h:65
ystdex::optional::operator*
_type && operator*()&&
Definition: optional.h:409
ystdex::details::optional_base< _type, true >::optional_base
optional_base(in_place_t, _tParams &&...args)
Definition: optional.h:141
yforward
#define yforward(_expr)
根据参数类型使用 std::forward 传递对应参数。
Definition: ydef.h:969
ystdex::is_cv
判断指定类型是否为 const 或 volatile 类型。
Definition: type_traits.hpp:842
ystdex::is_nothrow_moveable
Definition: type_traits.hpp:895
ystdex::or_
Definition: type_traits.hpp:412
ystdex::details::optional_base< _type, true >::operator=
optional_base & operator=(const optional_base &s)
Definition: optional.h:166
ystdex::details::optional_base< _type, true >::optional_base
optional_base(const optional_base &s)
Definition: optional.h:144
ystdex::optional::emplace
void emplace(std::initializer_list< _tOther > il, _tParams &&...args)
Definition: optional.h:347
ystdex::details::optional_base< _type, true >::is_engaged
bool is_engaged() const
Definition: optional.h:233
CHRLib::args
_tParams && args
Definition: CharacterProcessing.h:538
ystdex::optional::optional
optional()
Definition: optional.h:278
ystdex::is_copyable
Definition: type_traits.hpp:877
ystdex::optional::operator=
optional & operator=(const optional &o)
Definition: optional.h:315
ystdex::and_
逻辑操作元函数。
Definition: type_traits.hpp:394
ystdex::optional::value_or
_type value_or(_tOther &&other) const &
Definition: optional.h:455
ystdex::optional::operator*
const _type & operator*() const &
Definition: optional.h:403
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
ystdex::details::optional_base< _type, true >::~optional_base
~optional_base()
析构：空实现。
Definition: optional.h:162
ystdex::details::optional_base::operator=
optional_base & operator=(const optional_base &s)
Definition: optional.h:108
platform::bool
std::FILE *fp bool
Definition: FileIO.h:1187
ystdex::details::optional_base< _type, true >::optional_base
optional_base(const optional_base &&s)
Definition: optional.h:150
ystdex::optional::operator*
_type && operator*() const &&
Definition: optional.h:415
ystdex::bad_optional_access
可选值操作失败异常。
Definition: optional.h:79
ystdex::optional::base
details::optional_base< _type > base
Definition: optional.h:274