epoc32/include/stdapis/boost/smart_cast.hpp
branchSymbian2
changeset 2 2fe1408b6811
     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