YSTest: utility.hpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

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

- 文件列表
- 文件成员

utility.hpp
浏览该文件的文档.
1 /*
2 © 2010-2017 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
28 #ifndef YB_INC_ystdex_utility_hpp_
29 #define YB_INC_ystdex_utility_hpp_ 1
30
31 #include "type_pun.hpp" // for "type_pun.hpp", add_const_t,
32 // is_nothrow_constructible, is_nothrow_assignable, std::move, add_volatile_t,
33 // bool_, is_standard_layout, pun_storage_t, is_nothrow_swappable_with,
34 // std::swap, aligned_replace_cast, exclude_self_t, default_init,
35 // replace_storage_t;
36 #include <functional> // for std::bind, std::ref
37 #include "memory.hpp" // for std::addressof, yassume, ystdex::construct_in,
38 // ystdex::destruct_in;
39 #include "base.h" // for noncopyable, nonmovable;
40
41 namespace ystdex
42 {
43
49 template<typename _type>
50 inline add_const_t<_type>&
51 as_const(_type& t)
52 {
53 return t;
54 }
55
56
63 template<typename _type>
64 yimpl(enable_if_t)<is_nothrow_constructible<_type, volatile _type&&>()
65 && is_nothrow_assignable<_type&, volatile _type&&>()
66 && is_nothrow_assignable<volatile _type&, _type&&>()>
67 swap_volatile(_type& x, volatile _type& y)
68 ynoexcept(is_nothrow_constructible<_type, volatile _type&>()
69 && noexcept(x = std::move(y)) && noexcept(y = std::move(x)))
70 {
71 auto t(std::move(x));
72
73 x = std::move(y);
74 y = std::move(t);
75 }
76 template<typename _type>
77 inline auto
78 swap_volatile(volatile _type& x, _type& y)
79 ynoexcept_spec(ystdex::swap_volatile(y, x))
80 -> decltype(ystdex::swap_volatile(y, x))
81 {
82 ystdex::swap_volatile(y, x);
83 }
84 template<typename _type, size_t _vN>
85 void
86 swap_volatile(_type(&x)[_vN], add_volatile_t<_type[_vN]>& y)
87 ynoexcept(noexcept(ystdex::swap_volatile(x[0], y[0])))
88 {
89 auto first(std::addressof(x[0]));
90 auto first2(std::addressof(y[0]));
91
92 for(const auto last(first + _vN); first != last; yunseq(++first, ++first2))
93 ystdex::swap_volatile(*first, *first2);
94 }
96
98 namespace details
99 {
100
101 template<typename _type, typename _type2>
102 using swap_volatile_avail = bool_<is_volatile<remove_reference_t<_type>>::value
103 != is_volatile<remove_reference_t<_type2>>::value>;
104
105 #if YB_HAS_NOEXCEPT
106 template<typename _type, typename _type2>
107 using swap_volatile_noexcept = and_<swap_volatile_avail<_type, _type2>, bool_<
108 noexcept(swap_volatile(std::declval<_type>(), std::declval<_type2>()))>>;
109 #else
110 template<typename _type, typename _type2>
111 using swap_volatile_noexcept = swap_volatile_avail<_type, _type2>;
112 #endif
113
114 } // namespace details;
115
120 template<typename _type>
121 void
122 swap_underlying(_type& x, _type& y) ynothrow
123 {
124 static_assert(is_standard_layout<_type>(),
125 "Invalid underlying type found.");
126 using utype = pun_storage_t<_type>;
127
128 std::swap(ystdex::aligned_replace_cast<utype&>(x),
129 ystdex::aligned_replace_cast<utype&>(y));
130 }
131
138 template<typename _type, typename _type2, yimpl(typename
140 = enable_if_t<!details::swap_volatile_avail<_type, _type2>::value>)>
141 void
142 vswap(_type&& x, _type2&& y)
143 ynoexcept(is_nothrow_swappable_with<_type&&, _type2&&>())
144 {
145 using std::swap;
146
147 swap(yforward(x), yforward(y));
148 }
150
151 template<typename _type, typename _type2>
152 inline auto
153 vswap(_type&& x, _type2&& y) ynoexcept(detected_or_t<false_,
154 details::swap_volatile_noexcept, _type, _type2>())
155 -> yimpl(enable_if_t)<details::swap_volatile_avail<_type, _type2>::value>
156 {
157 swap_volatile(yforward(x), yforward(y));
158 }
160
161
162
168 template<typename _type, typename _type2 = _type>
169 inline _type&
170 copy_and_swap(_type& obj, const _type2& new_val)
171 {
172 using std::swap;
173 auto t(new_val);
174
175 swap(t, obj);
176 return obj;
177 }
178
183 template<typename _type, typename _type2 = _type>
184 inline _type
185 copy_or_move(bool copy, _type& obj)
186 {
187 if(copy)
188 return ystdex::as_const(obj);
189 return std::move(obj);
190 }
191
192 inline namespace cpp2014
193 {
194
195 #if __cpp_lib_exchange_function >= 201304 || __cplusplus > 201103L
196 using std::exchange;
197 #else
198
205 template<typename _type, typename _type2 = _type>
206 _type
207 exchange(_type& obj, _type2&& new_val)
208 {
209 _type old_val = std::move(obj);
210
211 obj = std::forward<_type2>(new_val);
212 return old_val;
213 }
214 #endif
215
216 } // inline namespace cpp2014;
217
218
226 template<typename _type>
227 yconstfn yimpl(enable_if_convertible_t)<_type, decay_t<_type>, decay_t<_type>>
228 decay_copy(_type&& arg)
229 {
230 return std::forward<_type>(arg);
231 }
232
233
238 template<typename _type, yimpl(typename = enable_if_t<is_enum<_type>::value>)>
239 yconstfn underlying_type_t<_type>
240 underlying(_type val) ynothrow
241 {
242 return underlying_type_t<_type>(val);
243 }
244
245
251 template<typename _type>
252 struct boxed_value
253 {
255 mutable _type value;
256
258
259 yconstfn
260 boxed_value() ynoexcept(is_nothrow_constructible<_type>())
261 : value()
262 {}
264 yconstfn
265 boxed_value(default_init_t) ynoexcept(is_nothrow_constructible<_type>())
266 {}
267 template<typename _tParam,
268 yimpl(typename = exclude_self_t<boxed_value, _tParam>)>
269 yconstfn
270 boxed_value(_tParam&& arg)
271 ynoexcept(is_nothrow_constructible<_type, _tParam&&>())
272 : value(yforward(arg))
273 {}
274 template<typename _tParam1, typename _tParam2, typename... _tParams>
275 yconstfn
276 boxed_value(_tParam1&& arg1, _tParam2&& arg2, _tParams&&... args)
277 ynoexcept(is_nothrow_constructible<_type, _tParam1&&, _tParam2&&,
278 _tParams&&...>())
279 : value(yforward(arg1), yforward(arg2), yforward(args)...)
280 {}
282
284 boxed_value(const boxed_value&) = default;
285 boxed_value(boxed_value&&) = default;
286
287 boxed_value&
288 operator=(const boxed_value&) = default;
289 boxed_value&
290 operator=(boxed_value&&) = default;
292
293 operator _type&() ynothrow
294 {
295 return value;
296 }
297
298 operator const _type&() const ynothrow
299 {
300 return value;
301 }
302 };
303
304
310 template<typename _type>
311 using classify_value_t = cond_t<std::is_class<_type>, _type,
312 boxed_value<_type>>;
313
314
321 template<typename _type, typename, typename...>
322 inline _type&
323 parameterize_static_object()
324 {
325 static _type obj;
326
327 return obj;
328 }
335 template<typename _type, size_t...>
336 inline _type&
337 parameterize_static_object()
338 {
339 static _type obj;
340
341 return obj;
342 }
343
344
354 template<typename _tKey, typename... _tKeys, typename _fInit,
355 typename... _tParams>
356 inline auto
357 get_init(_fInit&& f, _tParams&&... args) -> decltype(f(yforward(args)...))&
358 {
359 using obj_type = decltype(f(yforward(args)...));
360
361 auto& p(ystdex::parameterize_static_object<obj_type*, _tKey, _tKeys...>());
362
363 if(!p)
364 p = new obj_type(f(yforward(args)...));
365 return *p;
366 }
375 template<size_t... _vKeys, typename _fInit, typename... _tParams>
376 inline auto
377 get_init(_fInit&& f, _tParams&&... args) -> decltype(f(yforward(args)...))&
378 {
379 using obj_type = decltype(f(yforward(args)...));
380
381 auto& p(ystdex::parameterize_static_object<obj_type*, _vKeys...>());
382
383 if(!p)
384 p = new obj_type(f(yforward(args)...));
385 return *p;
386 }
387
388
410 template<class _type>
411 class nifty_counter
412 {
413 public:
414 using object_type = _type;
415
416 template<typename... _tParams>
417 nifty_counter(_tParams&&... args)
418 {
419 if(get_count()++ == 0)
420 get_object_ptr() = new _type(yforward(args)...);
421 }
423
424 ~nifty_counter()
426 {
427 if(--get_count() == 0)
428 delete get_object_ptr();
429 }
430
431 static object_type&
432 get() ynothrow
433 {
434 yassume(get_object_ptr());
435 return *get_object_ptr();
436 }
437
438 private:
439 static size_t&
440 get_count() ynothrow
441 {
442 ythread size_t count;
443
444 return count;
445 }
446 static object_type*&
447 get_object_ptr() ynothrow
448 {
449 ythread object_type* ptr;
450
451 return ptr;
452 }
453
454 public:
455 static size_t
456 use_count() ynothrow
457 {
458 return get_count();
459 }
461 };
462
463
483 template<typename _type, typename _tOnceFlag>
484 class call_once_init : private noncopyable, private nonmovable
485 {
486 public:
487 using object_type = _type;
488 using flag_type = _tOnceFlag;
489
490 private:
492 flag_type init_flag, uninit_flag;
494 replace_storage_t<_type> storage;
495
496 public:
497 template<typename... _tParams>
498 call_once_init(_tParams&&... args)
499 : init_flag(), uninit_flag()
500 {
501 call_once(init_flag, std::bind(ystdex::construct_in<_type,
502 _tParams&&...>, std::ref(get()), std::ref(args)...));
503 }
504 ~call_once_init()
505 {
506 call_once(init_flag, std::bind(ystdex::destruct_in<_type>,
507 std::ref(get())));
508 }
509
511 object_type&
512 get() ynothrow
513 {
514 return storage.template access<object_type>();
515 }
517 const object_type&
518 get() const ynothrow
519 {
520 return storage.template access<const object_type>();
521 }
522 };
523
524 } // namespace ystdex;
525
526 #if !YB_HAS_BUILTIN_NULLPTR
527 using ystdex::nullptr;
528 #endif
529
530 #endif
531
ystdex::boxed_value
包装类类型的值的对象。
Definition: utility.hpp:252
ystdex::boxed_value::operator=
boxed_value & operator=(const boxed_value &)=default
ystdex::swap_underlying
void swap_underlying(_type &x, _type &y)
交换相同标准布局类型可修改左值的存储。
Definition: utility.hpp:122
ystdex::default_init_t
默认初始化标记。
Definition: placement.hpp:48
yconstfn
#define yconstfn
指定编译时常量函数。
Definition: ydef.h:680
ystdex::nifty_counter::~nifty_counter
~nifty_counter()
Definition: utility.hpp:425
ystdex::call_once_init< YSLib::GUIApplication::InitBlock, once_flag >::flag_type
once_flag flag_type
Definition: utility.hpp:488
ystdex::nifty_counter::object_type
_type object_type
Definition: utility.hpp:414
type_pun.hpp
共享存储和直接转换。
ystdex::call_once_init
使用 call_once 的静态初始化管理器。
Definition: utility.hpp:484
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::false_
bool_< false > false_
Definition: type_traits.hpp:392
CHRLib::f
f(d, s)
ystdex::call_once_init::uninit_flag
flag_type uninit_flag
Definition: utility.hpp:492
ynoexcept_spec
#define ynoexcept_spec(...)
表达式 noexcept 异常规范。
Definition: ydef.h:794
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:262
ystdex::standard_layout_storage
任意标准布局类型对象提供空间的存储。
Definition: type_pun.hpp:307
ystdex::cpp2014::enable_if_t
typename enable_if< _bCond, _type >::type enable_if_t
Definition: type_traits.hpp:343
ystdex::call_once_init::object_type
_type object_type
Definition: utility.hpp:487
CHRLib::args
_tParams && args
Definition: CharacterProcessing.h:538
ystdex::nullptr
const class ystdex::nullptr_t nullptr
ystdex::call_once_init::~call_once_init
~call_once_init()
Definition: utility.hpp:504
ystdex::nifty_counter::use_count
static size_t use_count()
Definition: utility.hpp:456
ystdex::cpp2014::add_volatile_t
typename add_volatile< _type >::type add_volatile_t
Definition: type_traits.hpp:292
yunseq
#define yunseq
无序列依赖表达式组求值。
Definition: ydef.h:1022
ythread
#define ythread
线程局部存储：若实现支持，指定为 thread_local 。
Definition: ydef.h:806
ystdex::call_once_init::storage
replace_storage_t< _type > storage
Definition: utility.hpp:494
ystdex::boxed_value::boxed_value
boxed_value(_tParam1 &&arg1, _tParam2 &&arg2, _tParams &&...args)
Definition: utility.hpp:276
ystdex::detected_or_t
_t< detected_or< _tDefault, _gOp, _tParams... >> detected_or_t
Definition: type_traits.hpp:719
ystdex::decay_copy
enable_if_convertible_t< _type, decay_t< _type >, decay_t< _type > > decay_copy(_type &&arg)
退化复制。
Definition: utility.hpp:228
ystdex::copy_or_move
_type copy_or_move(bool copy, _type &obj)
按参数复制或转移。
Definition: utility.hpp:185
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:766
ystdex
特性测试宏。
Definition: ydef.h:822
ystdex::nifty_counter::nifty_counter
nifty_counter(_tParams &&...args)
Definition: utility.hpp:417
ystdex::cpp2014::exchange
_type exchange(_type &obj, _type2 &&new_val)
交换值并返回旧值。
Definition: utility.hpp:207
ystdex::details::swap_volatile_noexcept
swap_volatile_avail< _type, _type2 > swap_volatile_noexcept
Definition: utility.hpp:111
ystdex::call_once_init::call_once_init
call_once_init(_tParams &&...args)
Definition: utility.hpp:498
ystdex::boxed_value::boxed_value
boxed_value()
Definition: utility.hpp:260
ystdex::vswap
void vswap(_type &&x, _type2 &&y)
交换可能是 volatile 的左值或右值。
Definition: utility.hpp:142
base.h
基类实用设施。
memory.hpp
存储和智能指针特性。
ystdex::underlying
underlying_type_t< _type > underlying(_type val)
取枚举值的底层整数。
Definition: utility.hpp:240
ystdex::nonmovable
Definition: base.h:81
ystdex::swap
void swap(container_adaptor< _tSeqCon > &x, container_adaptor< _tSeqCon > &y)
Definition: container.hpp:179
ystdex::exclude_self_t
enable_if_t<!is_same< _tClass &, decay_t< _tParam > & >::value, _type > exclude_self_t
移除选择类类型的特定重载避免构造模板和复制/转移特殊成员函数冲突。
Definition: type_traits.hpp:748
ystdex::nifty_counter::get_count
static size_t & get_count()
Definition: utility.hpp:440
ystdex::single_thread::call_once
void call_once(once_flag &flag, _fCallable &&f, _tParams &&...args)
按标识调用函数，保证调用一次。
Definition: pseudo_mutex.h:1021
YSLib::GUIApplication::InitBlock
Definition: GUIApplication.h:202
ystdex::details::swap_volatile_avail
bool_< is_volatile< remove_reference_t< _type >>::value!=is_volatile< remove_reference_t< _type2 >>::value > swap_volatile_avail
Definition: utility.hpp:103
ystdex::classify_value_t
cond_t< std::is_class< _type >, _type, boxed_value< _type >> classify_value_t
包装非类类型为类类型。
Definition: utility.hpp:312
ystdex::nifty_counter
使用引用计数的静态初始化管理器。
Definition: utility.hpp:411
ystdex::noncopyable
不可复制对象：禁止派生类调用默认原型的复制构造函数和复制赋值操作符。
Definition: base.h:41
ystdex::copy_and_swap
_type & copy_and_swap(_type &obj, const _type2 &new_val)
复制后交换。
Definition: utility.hpp:170
yforward
#define yforward(_expr)
根据参数类型使用 std::forward 传递对应参数。
Definition: ydef.h:995
yassume
#define yassume(_expr)
假定：环境语义。
Definition: cassert.h:105
ystdex::pun_storage_t
aligned_storage_t< sizeof(_type), _vAlign > pun_storage_t
显式转换的替代对齐存储对齐存储类型。
Definition: type_pun.hpp:114
ystdex::enable_if_convertible_t
enable_if_t< is_convertible< _tFrom, _tTo >::value, _type > enable_if_convertible_t
Definition: type_traits.hpp:1052
ystdex::get_init
auto get_init(_fInit &&f, _tParams &&...args) -> decltype(f(std::forward< decltype(args)>(args)...))&
取类型标识和初始化调用指定的对象。
Definition: utility.hpp:357
ystdex::nifty_counter::get_object_ptr
static object_type *& get_object_ptr()
Definition: utility.hpp:447
ystdex::construct_in
void construct_in(_type &obj, _tParams &&...args)
以值初始化原地构造。
Definition: placement.hpp:154
ystdex::swap_volatile
enable_if_t< is_nothrow_constructible< _type, volatile _type && >)&&is_nothrow_assignable< _type &, volatile _type && >)&&is_nothrow_assignable< volatile _type &, _type && >)> swap_volatile(_type &x, volatile _type &y)
交换非 volatile 左值和 volatile 左值。
Definition: utility.hpp:67
ystdex::as_const
add_const_t< _type > & as_const(_type &t)
转换 const 引用。
Definition: utility.hpp:51
ystdex::boxed_value::boxed_value
boxed_value(_tParam &&arg)
Definition: utility.hpp:270
ystdex::is_nothrow_swappable_with
判断是否可以无抛出地调用 swap 。
Definition: type_traits.hpp:549
ystdex::call_once_init::init_flag
flag_type init_flag
Definition: utility.hpp:492
ystdex::and_
逻辑操作元函数。
Definition: type_traits.hpp:420
ystdex::ref
lref< _type > ref(_type &t)
构造引用包装。
Definition: ref.hpp:132
ystdex::boxed_value::boxed_value
boxed_value(default_init_t)
Definition: utility.hpp:265
ystdex::boxed_value::value
_type value
Definition: utility.hpp:255
ystdex::parameterize_static_object
_type & parameterize_static_object()
类型参数化静态对象。
Definition: utility.hpp:323
ynoexcept
#define ynoexcept(...)
YSLib 无异常抛出保证：指定特定的异常规范。
Definition: ydef.h:746
ystdex::bool_
std::integral_constant< bool, _vInt > bool_
Definition: type_traits.hpp:375
CHRLib::p
const auto p(d)