epoc32/include/stdapis/boost/smart_cast.hpp
branchSymbian2
changeset 2 2fe1408b6811
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/epoc32/include/stdapis/boost/smart_cast.hpp	Tue Mar 16 16:12:26 2010 +0000
@@ -0,0 +1,298 @@
+#ifndef BOOST_SMART_CAST_HPP
+#define BOOST_SMART_CAST_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// smart_cast.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// casting of pointers and references.  
+
+// In casting between different C++ classes, there are a number of
+// rules that have to be kept in mind in deciding whether to use
+// static_cast or dynamic_cast.  
+
+// a) dynamic casting can only be applied when one of the types is polymorphic
+// Otherwise static_cast must be used.
+// b) only dynamic casting can do runtime error checking
+// use of static_cast is generally un checked even when compiled for debug
+// c) static_cast would be considered faster than dynamic_cast.
+
+// If casting is applied to a template parameter, there is no apriori way
+// to know which of the two casting methods will be permitted or convenient.
+
+// smart_cast uses C++ type_traits, and program debug mode to select the
+// most convenient cast to use.
+
+#include <exception>
+#include <typeinfo>
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/identity.hpp>
+
+namespace boost {
+namespace smart_cast_impl {
+
+    template<class T>
+    struct reference {
+
+        struct polymorphic {
+
+            struct linear {
+                template<class U>
+                 static T cast(U & u){
+                    return static_cast<T>(u);
+                }
+            };
+
+            struct cross {
+                 template<class U>
+                static T cast(U & u){
+                    return dynamic_cast<T>(u);
+                }
+            };
+
+            template<class U>
+            static T cast(U & u){
+                // if we're in debug mode
+                #if ! defined(NDEBUG)                               \
+                || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) \
+                || defined(__MWERKS__)
+                    // do a checked dynamic cast
+                    return cross::cast(u);
+                #else
+                    // borland 5.51 chokes here so we can't use it
+                    // note: if remove_reference isn't function for these types
+                    // cross casting will be selected this will work but will
+                    // not be the most efficient method. This will conflict with
+                    // the original smart_cast motivation.
+                    typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                            BOOST_DEDUCED_TYPENAME mpl::and_<
+                                mpl::not_<is_base_and_derived<
+                                    BOOST_DEDUCED_TYPENAME remove_reference<T>::type,
+                                    U
+                                > >,
+                                mpl::not_<is_base_and_derived<
+                                    U,
+                                    BOOST_DEDUCED_TYPENAME remove_reference<T>::type
+                                > >
+                            >,
+                            // borland chokes w/o full qualification here
+                            mpl::identity<cross>,
+                            mpl::identity<linear>
+                    >::type typex;
+                    // typex works around gcc 2.95 issue
+                    return typex::cast(u);
+                #endif
+            }
+        };
+
+        struct non_polymorphic {
+            template<class U>
+             static T cast(U & u){
+                return static_cast<T>(u);
+            }
+        };
+        template<class U>
+        static T cast(U & u){
+            #if defined(__BORLANDC__)
+                return mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type::cast(u);
+            #else
+                typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type typex;
+                return typex::cast(u);
+            #endif
+        }
+    };
+
+    template<class T>
+    struct pointer {
+
+        struct polymorphic {
+            // unfortunately, this below fails to work for virtual base 
+            // classes.  need has_virtual_base to do this.
+            // Subject for further study
+            #if 0
+            struct linear {
+                template<class U>
+                 static T cast(U * u){
+                    return static_cast<T>(u);
+                }
+            };
+
+            struct cross {
+                template<class U>
+                static T cast(U * u){
+                    T tmp = dynamic_cast<T>(u);
+                    #ifndef NDEBUG
+                        if ( tmp == 0 ) throw std::bad_cast();
+                    #endif
+                    return tmp;
+                }
+            };
+
+            template<class U>
+            static T cast(U * u){
+                // if we're in debug mode
+                #if ! defined(NDEBUG) || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
+                    // do a checked dynamic cast
+                    return cross::cast(u);
+                #else
+                    // borland 5.51 chokes here so we can't use it
+                    // note: if remove_pointer isn't function for these types
+                    // cross casting will be selected this will work but will
+                    // not be the most efficient method. This will conflict with
+                    // the original smart_cast motivation.
+                    typedef
+                        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                            BOOST_DEDUCED_TYPENAME mpl::and_<
+                                mpl::not_<is_base_and_derived<
+                                    BOOST_DEDUCED_TYPENAME remove_pointer<T>::type,
+                                    U
+                                > >,
+                                mpl::not_<is_base_and_derived<
+                                    U,
+                                    BOOST_DEDUCED_TYPENAME remove_pointer<T>::type
+                                > >
+                            >,
+                            // borland chokes w/o full qualification here
+                            mpl::identity<cross>,
+                            mpl::identity<linear>
+                        >::type typex;
+                    return typex::cast(u);
+                #endif
+            }
+            #else
+            template<class U>
+            static T cast(U * u){
+                T tmp = dynamic_cast<T>(u);
+                #ifndef NDEBUG
+                    if ( tmp == 0 ) throw std::bad_cast();
+                #endif
+                return tmp;
+            }
+            #endif
+        };
+
+        struct non_polymorphic {
+            template<class U>
+             static T cast(U * u){
+                return static_cast<T>(u);
+            }
+        };
+
+        template<class U>
+        static T cast(U * u){
+            #if defined(__BORLANDC__)
+                return mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type::cast(u);
+            #else
+                typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type typex;
+                return typex::cast(u);
+            #endif
+        }
+
+    };
+
+    template<class TPtr>
+    struct void_pointer {
+        template<class UPtr>
+        static TPtr cast(UPtr uptr){
+            return static_cast<TPtr>(uptr);
+        }
+    };
+
+    template<class T>
+    struct error {
+        // if we get here, its because we are using one argument in the
+        // cast on a system which doesn't support partial template 
+        // specialization
+        template<class U>
+        static T cast(U u){
+            BOOST_STATIC_ASSERT(sizeof(T)==0);
+            return * static_cast<T *>(NULL);
+        }
+    };
+
+} // smart_cast_impl
+
+// this implements:
+// smart_cast<Target *, Source *>(Source * s)
+// smart_cast<Target &, Source &>(s)
+// note that it will fail with
+// smart_cast<Target &>(s)
+template<class T, class U>
+T smart_cast(U u) {
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            BOOST_DEDUCED_TYPENAME mpl::or_<
+                boost::is_same<void *, U>,
+                boost::is_same<void *, T>,
+                boost::is_same<const void *, U>,
+                boost::is_same<const void *, T>
+            >,
+            mpl::identity<smart_cast_impl::void_pointer<T> >,
+        // else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_pointer<U>,
+            mpl::identity<smart_cast_impl::pointer<T> >,
+        // else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_reference<U>,
+            mpl::identity<smart_cast_impl::reference<T> >,
+        // else
+            mpl::identity<smart_cast_impl::error<T>
+        >
+        >
+        >
+        >::type typex;
+    return typex::cast(u);
+}
+
+// this implements:
+// smart_cast_reference<Target &>(Source & s)
+template<class T, class U>
+T smart_cast_reference(U & u) {
+    return smart_cast_impl::reference<T>::cast(u);
+}
+
+} // namespace boost
+
+#endif // BOOST_SMART_CAST_HPP