YSTest: cast.hpp 源文件

YSTest PreAlpha_b400_20130424 The YSLib Test Project

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

- 文件列表
- 文件成员

全部 类 命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义 组 页
cast.hpp
浏览该文件的文档.
1 ﻿/*
2 Copyright by FrankHB 2010 - 2013.
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_cast_hpp_
29 #define YB_INC_ystdex_cast_hpp_ 1
30
31 #include "type_op.hpp"
32 #include <memory>
33 #include <typeinfo> // for dynamic_cast;
34 #include <initializer_list> // for std::initialize_list;
35
36 namespace ystdex
37 {
38
53 template<typename _tDst, typename _tSrc>
54 inline _tDst
55 union_cast(_tSrc x) ynothrow
56 {
57 static_assert(is_pod<_tDst>::value, "Non-POD destination type found.");
58 static_assert(sizeof(_tSrc) == sizeof(_tDst), "Incompatible types found.");
59
60 union
61 {
62 _tSrc x;
63 _tDst y;
64 } u = {x};
65 return u.y;
66 }
67
68
75 template<typename _tDst, typename... _tSrc>
76 yconstfn std::initializer_list<_tDst>
77 initializer_cast(_tSrc&&... x)
78 {
79 return {_tDst(yforward(x))...};
80 }
81
82
93 template <typename _pDst, class _tSrc>
94 inline _pDst
95 polymorphic_cast(_tSrc* x)
96 {
97 static_assert(is_polymorphic<_tSrc>::value, "Non-polymorphic class found.");
98 static_assert(is_pointer<_pDst>::value, "Non-pointer destination found.");
99
100 const auto tmp(dynamic_cast<_pDst>(x));
101
102 if(!tmp)
103 throw std::bad_cast();
104 return tmp;
105 }
106
118 template <typename _pDst, class _tSrc>
119 inline _pDst
120 polymorphic_downcast(_tSrc* x)
121 {
122 static_assert(is_polymorphic<_tSrc>::value, "Non-polymorphic class found.");
123 static_assert(is_pointer<_pDst>::value, "Non-pointer destination found.");
124 static_assert(is_base_of<_tSrc, typename remove_cv<typename remove_pointer<
125 _pDst>::type>::type>::value, "Wrong destination type found.");
126
127 yassume(dynamic_cast<_pDst>(x) == x);
128
129 return static_cast<_pDst>(x);
130 }
140 template <typename _rDst, class _tSrc>
141 yconstfn _rDst&
142 polymorphic_downcast(_tSrc& x)
143 {
144 static_assert(is_reference<_rDst>::value,
145 "Non-reference destination found.");
146
147 return *ystdex::polymorphic_downcast<typename remove_reference<
148 _rDst>::type*>(std::addressof(x));
149 }
150
163 template <typename _pDst, class _tSrc>
164 inline _pDst
165 polymorphic_crosscast(_tSrc* x)
166 {
167 static_assert(is_polymorphic<_tSrc>::value, "Non-polymorphic class found.");
168 static_assert(is_pointer<_pDst>::value, "Non-pointer destination found.");
169
170 auto p(dynamic_cast<_pDst>(x));
171
172 yassume(p);
173 return p;
174 }
184 template <typename _rDst, class _tSrc>
185 yconstfn _rDst&
186 polymorphic_crosscast(_tSrc& x)
187 {
188 static_assert(is_reference<_rDst>::value,
189 "Non-reference destination found.");
190
191 return *ystdex::polymorphic_crosscast<typename remove_reference<
192 _rDst>::type*>(std::addressof(x));
193 }
194
195
196 namespace details
197 {
198
199 template<typename _tFrom, typename _tTo, bool _bNonVirtualDownCast>
200 struct _general_polymorphic_cast_helper
201 {
202 static yconstfn _tTo
203 cast(_tFrom x)
204 {
205 return ystdex::polymorphic_downcast<_tTo>(x);
206 }
207 };
208 template<typename _tFrom, typename _tTo>
209 struct _general_polymorphic_cast_helper<_tFrom, _tTo, false>
210 {
211 static yconstfn _tTo
212 cast(_tFrom x)
213 {
214 return dynamic_cast<_tTo>(x);
215 }
216 };
217
218 template<typename _tFrom, typename _tTo, bool _bUseStaticCast>
219 struct _general_cast_helper
220 {
221 static yconstfn _tTo
222 cast(_tFrom x)
223 {
224 return _tTo(x);
225 }
226 };
227 template<typename _tFrom, typename _tTo>
228 struct _general_cast_helper<_tFrom, _tTo, false>
229 {
230 static yconstfn _tTo
231 cast(_tFrom x)
232 {
233 return _general_polymorphic_cast_helper<_tFrom, _tTo, (is_base_of<
234 _tFrom, _tTo>::value && !has_common_nonempty_virtual_base<typename
235 remove_rp<_tFrom>::type, typename remove_rp<_tTo>::type>::value)
236 >::cast(x);
237 }
238 };
239 template<typename _type>
240 struct _general_cast_helper<_type, _type, true>
241 {
242 static inline _type
243 cast(_type x)
244 {
245 return x;
246 }
247 };
248 template<typename _type>
249 struct _general_cast_helper<_type, _type, false>
250 {
251 static yconstfn _type
252 cast(_type x)
253 {
254 return x;
255 }
256 };
257
258 template<typename _tFrom, typename _tTo>
259 struct _general_cast_type_helper
260 : public integral_constant<bool, is_convertible<_tFrom, _tTo>::value>
261 {};
262
263 } // namespace details;
264
278 template<typename _tDst, typename _tSrc>
279 yconstfn _tDst
280 general_cast(_tSrc* x)
281 {
282 return details::_general_cast_helper<_tSrc*, _tDst,
283 details::_general_cast_type_helper<_tSrc*, _tDst>::value>::cast(x);
284 }
285 template<typename _tDst, typename _tSrc>
286 yconstfn _tDst
287 general_cast(_tSrc& x)
288 {
289 return details::_general_cast_helper<_tSrc&, _tDst,
290 details::_general_cast_type_helper<_tSrc&, _tDst>::value>::cast(x);
291 }
292 template<typename _tDst, typename _tSrc>
293 yconstfn const _tDst
294 general_cast(const _tSrc& x)
295 {
296 return details::_general_cast_helper<const _tSrc&, _tDst, details
297 ::_general_cast_type_helper<const _tSrc&, const _tDst>::value>::cast(x);
298 }
300
301 } // namespace ystdex;
302
303 #endif
304