epoc32/include/stdapis/boost/smart_cast.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
     1 #ifndef BOOST_SMART_CAST_HPP
     2 #define BOOST_SMART_CAST_HPP
     3 
     4 // MS compatible compilers support #pragma once
     5 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
     6 # pragma once
     7 #endif
     8 
     9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
    10 // smart_cast.hpp:
    11 
    12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
    13 // Use, modification and distribution is subject to the Boost Software
    14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    15 // http://www.boost.org/LICENSE_1_0.txt)
    16 
    17 //  See http://www.boost.org for updates, documentation, and revision history.
    18 
    19 // casting of pointers and references.  
    20 
    21 // In casting between different C++ classes, there are a number of
    22 // rules that have to be kept in mind in deciding whether to use
    23 // static_cast or dynamic_cast.  
    24 
    25 // a) dynamic casting can only be applied when one of the types is polymorphic
    26 // Otherwise static_cast must be used.
    27 // b) only dynamic casting can do runtime error checking
    28 // use of static_cast is generally un checked even when compiled for debug
    29 // c) static_cast would be considered faster than dynamic_cast.
    30 
    31 // If casting is applied to a template parameter, there is no apriori way
    32 // to know which of the two casting methods will be permitted or convenient.
    33 
    34 // smart_cast uses C++ type_traits, and program debug mode to select the
    35 // most convenient cast to use.
    36 
    37 #include <exception>
    38 #include <typeinfo>
    39 
    40 #include <boost/config.hpp>
    41 #include <boost/static_assert.hpp>
    42 
    43 #include <boost/type_traits/is_base_and_derived.hpp>
    44 #include <boost/type_traits/is_polymorphic.hpp>
    45 #include <boost/type_traits/is_pointer.hpp>
    46 #include <boost/type_traits/is_reference.hpp>
    47 #include <boost/type_traits/is_same.hpp>
    48 #include <boost/type_traits/remove_pointer.hpp>
    49 #include <boost/type_traits/remove_reference.hpp>
    50 
    51 #include <boost/mpl/eval_if.hpp>
    52 #include <boost/mpl/if.hpp>
    53 #include <boost/mpl/or.hpp>
    54 #include <boost/mpl/and.hpp>
    55 #include <boost/mpl/not.hpp>
    56 #include <boost/mpl/identity.hpp>
    57 
    58 namespace boost {
    59 namespace smart_cast_impl {
    60 
    61     template<class T>
    62     struct reference {
    63 
    64         struct polymorphic {
    65 
    66             struct linear {
    67                 template<class U>
    68                  static T cast(U & u){
    69                     return static_cast<T>(u);
    70                 }
    71             };
    72 
    73             struct cross {
    74                  template<class U>
    75                 static T cast(U & u){
    76                     return dynamic_cast<T>(u);
    77                 }
    78             };
    79 
    80             template<class U>
    81             static T cast(U & u){
    82                 // if we're in debug mode
    83                 #if ! defined(NDEBUG)                               \
    84                 || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) \
    85                 || defined(__MWERKS__)
    86                     // do a checked dynamic cast
    87                     return cross::cast(u);
    88                 #else
    89                     // borland 5.51 chokes here so we can't use it
    90                     // note: if remove_reference isn't function for these types
    91                     // cross casting will be selected this will work but will
    92                     // not be the most efficient method. This will conflict with
    93                     // the original smart_cast motivation.
    94                     typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
    95                             BOOST_DEDUCED_TYPENAME mpl::and_<
    96                                 mpl::not_<is_base_and_derived<
    97                                     BOOST_DEDUCED_TYPENAME remove_reference<T>::type,
    98                                     U
    99                                 > >,
   100                                 mpl::not_<is_base_and_derived<
   101                                     U,
   102                                     BOOST_DEDUCED_TYPENAME remove_reference<T>::type
   103                                 > >
   104                             >,
   105                             // borland chokes w/o full qualification here
   106                             mpl::identity<cross>,
   107                             mpl::identity<linear>
   108                     >::type typex;
   109                     // typex works around gcc 2.95 issue
   110                     return typex::cast(u);
   111                 #endif
   112             }
   113         };
   114 
   115         struct non_polymorphic {
   116             template<class U>
   117              static T cast(U & u){
   118                 return static_cast<T>(u);
   119             }
   120         };
   121         template<class U>
   122         static T cast(U & u){
   123             #if defined(__BORLANDC__)
   124                 return mpl::eval_if<
   125                     boost::is_polymorphic<U>,
   126                     mpl::identity<polymorphic>,
   127                     mpl::identity<non_polymorphic>
   128                 >::type::cast(u);
   129             #else
   130                 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
   131                     boost::is_polymorphic<U>,
   132                     mpl::identity<polymorphic>,
   133                     mpl::identity<non_polymorphic>
   134                 >::type typex;
   135                 return typex::cast(u);
   136             #endif
   137         }
   138     };
   139 
   140     template<class T>
   141     struct pointer {
   142 
   143         struct polymorphic {
   144             // unfortunately, this below fails to work for virtual base 
   145             // classes.  need has_virtual_base to do this.
   146             // Subject for further study
   147             #if 0
   148             struct linear {
   149                 template<class U>
   150                  static T cast(U * u){
   151                     return static_cast<T>(u);
   152                 }
   153             };
   154 
   155             struct cross {
   156                 template<class U>
   157                 static T cast(U * u){
   158                     T tmp = dynamic_cast<T>(u);
   159                     #ifndef NDEBUG
   160                         if ( tmp == 0 ) throw std::bad_cast();
   161                     #endif
   162                     return tmp;
   163                 }
   164             };
   165 
   166             template<class U>
   167             static T cast(U * u){
   168                 // if we're in debug mode
   169                 #if ! defined(NDEBUG) || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
   170                     // do a checked dynamic cast
   171                     return cross::cast(u);
   172                 #else
   173                     // borland 5.51 chokes here so we can't use it
   174                     // note: if remove_pointer isn't function for these types
   175                     // cross casting will be selected this will work but will
   176                     // not be the most efficient method. This will conflict with
   177                     // the original smart_cast motivation.
   178                     typedef
   179                         BOOST_DEDUCED_TYPENAME mpl::eval_if<
   180                             BOOST_DEDUCED_TYPENAME mpl::and_<
   181                                 mpl::not_<is_base_and_derived<
   182                                     BOOST_DEDUCED_TYPENAME remove_pointer<T>::type,
   183                                     U
   184                                 > >,
   185                                 mpl::not_<is_base_and_derived<
   186                                     U,
   187                                     BOOST_DEDUCED_TYPENAME remove_pointer<T>::type
   188                                 > >
   189                             >,
   190                             // borland chokes w/o full qualification here
   191                             mpl::identity<cross>,
   192                             mpl::identity<linear>
   193                         >::type typex;
   194                     return typex::cast(u);
   195                 #endif
   196             }
   197             #else
   198             template<class U>
   199             static T cast(U * u){
   200                 T tmp = dynamic_cast<T>(u);
   201                 #ifndef NDEBUG
   202                     if ( tmp == 0 ) throw std::bad_cast();
   203                 #endif
   204                 return tmp;
   205             }
   206             #endif
   207         };
   208 
   209         struct non_polymorphic {
   210             template<class U>
   211              static T cast(U * u){
   212                 return static_cast<T>(u);
   213             }
   214         };
   215 
   216         template<class U>
   217         static T cast(U * u){
   218             #if defined(__BORLANDC__)
   219                 return mpl::eval_if<
   220                     boost::is_polymorphic<U>,
   221                     mpl::identity<polymorphic>,
   222                     mpl::identity<non_polymorphic>
   223                 >::type::cast(u);
   224             #else
   225                 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
   226                     boost::is_polymorphic<U>,
   227                     mpl::identity<polymorphic>,
   228                     mpl::identity<non_polymorphic>
   229                 >::type typex;
   230                 return typex::cast(u);
   231             #endif
   232         }
   233 
   234     };
   235 
   236     template<class TPtr>
   237     struct void_pointer {
   238         template<class UPtr>
   239         static TPtr cast(UPtr uptr){
   240             return static_cast<TPtr>(uptr);
   241         }
   242     };
   243 
   244     template<class T>
   245     struct error {
   246         // if we get here, its because we are using one argument in the
   247         // cast on a system which doesn't support partial template 
   248         // specialization
   249         template<class U>
   250         static T cast(U u){
   251             BOOST_STATIC_ASSERT(sizeof(T)==0);
   252             return * static_cast<T *>(NULL);
   253         }
   254     };
   255 
   256 } // smart_cast_impl
   257 
   258 // this implements:
   259 // smart_cast<Target *, Source *>(Source * s)
   260 // smart_cast<Target &, Source &>(s)
   261 // note that it will fail with
   262 // smart_cast<Target &>(s)
   263 template<class T, class U>
   264 T smart_cast(U u) {
   265     typedef
   266         BOOST_DEDUCED_TYPENAME mpl::eval_if<
   267             BOOST_DEDUCED_TYPENAME mpl::or_<
   268                 boost::is_same<void *, U>,
   269                 boost::is_same<void *, T>,
   270                 boost::is_same<const void *, U>,
   271                 boost::is_same<const void *, T>
   272             >,
   273             mpl::identity<smart_cast_impl::void_pointer<T> >,
   274         // else
   275         BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_pointer<U>,
   276             mpl::identity<smart_cast_impl::pointer<T> >,
   277         // else
   278         BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_reference<U>,
   279             mpl::identity<smart_cast_impl::reference<T> >,
   280         // else
   281             mpl::identity<smart_cast_impl::error<T>
   282         >
   283         >
   284         >
   285         >::type typex;
   286     return typex::cast(u);
   287 }
   288 
   289 // this implements:
   290 // smart_cast_reference<Target &>(Source & s)
   291 template<class T, class U>
   292 T smart_cast_reference(U & u) {
   293     return smart_cast_impl::reference<T>::cast(u);
   294 }
   295 
   296 } // namespace boost
   297 
   298 #endif // BOOST_SMART_CAST_HPP