1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/epoc32/include/stdapis/boost/smart_cast.hpp Tue Mar 16 16:12:26 2010 +0000
1.3 @@ -0,0 +1,298 @@
1.4 +#ifndef BOOST_SMART_CAST_HPP
1.5 +#define BOOST_SMART_CAST_HPP
1.6 +
1.7 +// MS compatible compilers support #pragma once
1.8 +#if defined(_MSC_VER) && (_MSC_VER >= 1020)
1.9 +# pragma once
1.10 +#endif
1.11 +
1.12 +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
1.13 +// smart_cast.hpp:
1.14 +
1.15 +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
1.16 +// Use, modification and distribution is subject to the Boost Software
1.17 +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
1.18 +// http://www.boost.org/LICENSE_1_0.txt)
1.19 +
1.20 +// See http://www.boost.org for updates, documentation, and revision history.
1.21 +
1.22 +// casting of pointers and references.
1.23 +
1.24 +// In casting between different C++ classes, there are a number of
1.25 +// rules that have to be kept in mind in deciding whether to use
1.26 +// static_cast or dynamic_cast.
1.27 +
1.28 +// a) dynamic casting can only be applied when one of the types is polymorphic
1.29 +// Otherwise static_cast must be used.
1.30 +// b) only dynamic casting can do runtime error checking
1.31 +// use of static_cast is generally un checked even when compiled for debug
1.32 +// c) static_cast would be considered faster than dynamic_cast.
1.33 +
1.34 +// If casting is applied to a template parameter, there is no apriori way
1.35 +// to know which of the two casting methods will be permitted or convenient.
1.36 +
1.37 +// smart_cast uses C++ type_traits, and program debug mode to select the
1.38 +// most convenient cast to use.
1.39 +
1.40 +#include <exception>
1.41 +#include <typeinfo>
1.42 +
1.43 +#include <boost/config.hpp>
1.44 +#include <boost/static_assert.hpp>
1.45 +
1.46 +#include <boost/type_traits/is_base_and_derived.hpp>
1.47 +#include <boost/type_traits/is_polymorphic.hpp>
1.48 +#include <boost/type_traits/is_pointer.hpp>
1.49 +#include <boost/type_traits/is_reference.hpp>
1.50 +#include <boost/type_traits/is_same.hpp>
1.51 +#include <boost/type_traits/remove_pointer.hpp>
1.52 +#include <boost/type_traits/remove_reference.hpp>
1.53 +
1.54 +#include <boost/mpl/eval_if.hpp>
1.55 +#include <boost/mpl/if.hpp>
1.56 +#include <boost/mpl/or.hpp>
1.57 +#include <boost/mpl/and.hpp>
1.58 +#include <boost/mpl/not.hpp>
1.59 +#include <boost/mpl/identity.hpp>
1.60 +
1.61 +namespace boost {
1.62 +namespace smart_cast_impl {
1.63 +
1.64 + template<class T>
1.65 + struct reference {
1.66 +
1.67 + struct polymorphic {
1.68 +
1.69 + struct linear {
1.70 + template<class U>
1.71 + static T cast(U & u){
1.72 + return static_cast<T>(u);
1.73 + }
1.74 + };
1.75 +
1.76 + struct cross {
1.77 + template<class U>
1.78 + static T cast(U & u){
1.79 + return dynamic_cast<T>(u);
1.80 + }
1.81 + };
1.82 +
1.83 + template<class U>
1.84 + static T cast(U & u){
1.85 + // if we're in debug mode
1.86 + #if ! defined(NDEBUG) \
1.87 + || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) \
1.88 + || defined(__MWERKS__)
1.89 + // do a checked dynamic cast
1.90 + return cross::cast(u);
1.91 + #else
1.92 + // borland 5.51 chokes here so we can't use it
1.93 + // note: if remove_reference isn't function for these types
1.94 + // cross casting will be selected this will work but will
1.95 + // not be the most efficient method. This will conflict with
1.96 + // the original smart_cast motivation.
1.97 + typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
1.98 + BOOST_DEDUCED_TYPENAME mpl::and_<
1.99 + mpl::not_<is_base_and_derived<
1.100 + BOOST_DEDUCED_TYPENAME remove_reference<T>::type,
1.101 + U
1.102 + > >,
1.103 + mpl::not_<is_base_and_derived<
1.104 + U,
1.105 + BOOST_DEDUCED_TYPENAME remove_reference<T>::type
1.106 + > >
1.107 + >,
1.108 + // borland chokes w/o full qualification here
1.109 + mpl::identity<cross>,
1.110 + mpl::identity<linear>
1.111 + >::type typex;
1.112 + // typex works around gcc 2.95 issue
1.113 + return typex::cast(u);
1.114 + #endif
1.115 + }
1.116 + };
1.117 +
1.118 + struct non_polymorphic {
1.119 + template<class U>
1.120 + static T cast(U & u){
1.121 + return static_cast<T>(u);
1.122 + }
1.123 + };
1.124 + template<class U>
1.125 + static T cast(U & u){
1.126 + #if defined(__BORLANDC__)
1.127 + return mpl::eval_if<
1.128 + boost::is_polymorphic<U>,
1.129 + mpl::identity<polymorphic>,
1.130 + mpl::identity<non_polymorphic>
1.131 + >::type::cast(u);
1.132 + #else
1.133 + typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
1.134 + boost::is_polymorphic<U>,
1.135 + mpl::identity<polymorphic>,
1.136 + mpl::identity<non_polymorphic>
1.137 + >::type typex;
1.138 + return typex::cast(u);
1.139 + #endif
1.140 + }
1.141 + };
1.142 +
1.143 + template<class T>
1.144 + struct pointer {
1.145 +
1.146 + struct polymorphic {
1.147 + // unfortunately, this below fails to work for virtual base
1.148 + // classes. need has_virtual_base to do this.
1.149 + // Subject for further study
1.150 + #if 0
1.151 + struct linear {
1.152 + template<class U>
1.153 + static T cast(U * u){
1.154 + return static_cast<T>(u);
1.155 + }
1.156 + };
1.157 +
1.158 + struct cross {
1.159 + template<class U>
1.160 + static T cast(U * u){
1.161 + T tmp = dynamic_cast<T>(u);
1.162 + #ifndef NDEBUG
1.163 + if ( tmp == 0 ) throw std::bad_cast();
1.164 + #endif
1.165 + return tmp;
1.166 + }
1.167 + };
1.168 +
1.169 + template<class U>
1.170 + static T cast(U * u){
1.171 + // if we're in debug mode
1.172 + #if ! defined(NDEBUG) || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
1.173 + // do a checked dynamic cast
1.174 + return cross::cast(u);
1.175 + #else
1.176 + // borland 5.51 chokes here so we can't use it
1.177 + // note: if remove_pointer isn't function for these types
1.178 + // cross casting will be selected this will work but will
1.179 + // not be the most efficient method. This will conflict with
1.180 + // the original smart_cast motivation.
1.181 + typedef
1.182 + BOOST_DEDUCED_TYPENAME mpl::eval_if<
1.183 + BOOST_DEDUCED_TYPENAME mpl::and_<
1.184 + mpl::not_<is_base_and_derived<
1.185 + BOOST_DEDUCED_TYPENAME remove_pointer<T>::type,
1.186 + U
1.187 + > >,
1.188 + mpl::not_<is_base_and_derived<
1.189 + U,
1.190 + BOOST_DEDUCED_TYPENAME remove_pointer<T>::type
1.191 + > >
1.192 + >,
1.193 + // borland chokes w/o full qualification here
1.194 + mpl::identity<cross>,
1.195 + mpl::identity<linear>
1.196 + >::type typex;
1.197 + return typex::cast(u);
1.198 + #endif
1.199 + }
1.200 + #else
1.201 + template<class U>
1.202 + static T cast(U * u){
1.203 + T tmp = dynamic_cast<T>(u);
1.204 + #ifndef NDEBUG
1.205 + if ( tmp == 0 ) throw std::bad_cast();
1.206 + #endif
1.207 + return tmp;
1.208 + }
1.209 + #endif
1.210 + };
1.211 +
1.212 + struct non_polymorphic {
1.213 + template<class U>
1.214 + static T cast(U * u){
1.215 + return static_cast<T>(u);
1.216 + }
1.217 + };
1.218 +
1.219 + template<class U>
1.220 + static T cast(U * u){
1.221 + #if defined(__BORLANDC__)
1.222 + return mpl::eval_if<
1.223 + boost::is_polymorphic<U>,
1.224 + mpl::identity<polymorphic>,
1.225 + mpl::identity<non_polymorphic>
1.226 + >::type::cast(u);
1.227 + #else
1.228 + typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
1.229 + boost::is_polymorphic<U>,
1.230 + mpl::identity<polymorphic>,
1.231 + mpl::identity<non_polymorphic>
1.232 + >::type typex;
1.233 + return typex::cast(u);
1.234 + #endif
1.235 + }
1.236 +
1.237 + };
1.238 +
1.239 + template<class TPtr>
1.240 + struct void_pointer {
1.241 + template<class UPtr>
1.242 + static TPtr cast(UPtr uptr){
1.243 + return static_cast<TPtr>(uptr);
1.244 + }
1.245 + };
1.246 +
1.247 + template<class T>
1.248 + struct error {
1.249 + // if we get here, its because we are using one argument in the
1.250 + // cast on a system which doesn't support partial template
1.251 + // specialization
1.252 + template<class U>
1.253 + static T cast(U u){
1.254 + BOOST_STATIC_ASSERT(sizeof(T)==0);
1.255 + return * static_cast<T *>(NULL);
1.256 + }
1.257 + };
1.258 +
1.259 +} // smart_cast_impl
1.260 +
1.261 +// this implements:
1.262 +// smart_cast<Target *, Source *>(Source * s)
1.263 +// smart_cast<Target &, Source &>(s)
1.264 +// note that it will fail with
1.265 +// smart_cast<Target &>(s)
1.266 +template<class T, class U>
1.267 +T smart_cast(U u) {
1.268 + typedef
1.269 + BOOST_DEDUCED_TYPENAME mpl::eval_if<
1.270 + BOOST_DEDUCED_TYPENAME mpl::or_<
1.271 + boost::is_same<void *, U>,
1.272 + boost::is_same<void *, T>,
1.273 + boost::is_same<const void *, U>,
1.274 + boost::is_same<const void *, T>
1.275 + >,
1.276 + mpl::identity<smart_cast_impl::void_pointer<T> >,
1.277 + // else
1.278 + BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_pointer<U>,
1.279 + mpl::identity<smart_cast_impl::pointer<T> >,
1.280 + // else
1.281 + BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_reference<U>,
1.282 + mpl::identity<smart_cast_impl::reference<T> >,
1.283 + // else
1.284 + mpl::identity<smart_cast_impl::error<T>
1.285 + >
1.286 + >
1.287 + >
1.288 + >::type typex;
1.289 + return typex::cast(u);
1.290 +}
1.291 +
1.292 +// this implements:
1.293 +// smart_cast_reference<Target &>(Source & s)
1.294 +template<class T, class U>
1.295 +T smart_cast_reference(U & u) {
1.296 + return smart_cast_impl::reference<T>::cast(u);
1.297 +}
1.298 +
1.299 +} // namespace boost
1.300 +
1.301 +#endif // BOOST_SMART_CAST_HPP