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
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 
196 namespace details
197 {
198 
199 template<typename _tFrom, typename _tTo, bool _bNonVirtualDownCast>
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>
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
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>
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,
284 }
285 template<typename _tDst, typename _tSrc>
286 yconstfn _tDst
287 general_cast(_tSrc& x)
288 {
289  return details::_general_cast_helper<_tSrc&, _tDst,
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
298 }
300 
301 } // namespace ystdex;
302 
303 #endif
304