You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							309 lines
						
					
					
						
							8.3 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							309 lines
						
					
					
						
							8.3 KiB
						
					
					
				
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * File:        stlsoft/conversion/ptr_cast.hpp
							 | 
						|
								 *
							 | 
						|
								 * Purpose:     A cast that throws bad_cast for dynamic pointer casting, as well
							 | 
						|
								 *              as references.
							 | 
						|
								 *
							 | 
						|
								 * Created:     28th December 2002
							 | 
						|
								 * Updated:     10th August 2009
							 | 
						|
								 *
							 | 
						|
								 * Home:        http://stlsoft.org/
							 | 
						|
								 *
							 | 
						|
								 * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
							 | 
						|
								 * All rights reserved.
							 | 
						|
								 *
							 | 
						|
								 * Redistribution and use in source and binary forms, with or without
							 | 
						|
								 * modification, are permitted provided that the following conditions are met:
							 | 
						|
								 *
							 | 
						|
								 * - Redistributions of source code must retain the above copyright notice, this
							 | 
						|
								 *   list of conditions and the following disclaimer.
							 | 
						|
								 * - Redistributions in binary form must reproduce the above copyright notice,
							 | 
						|
								 *   this list of conditions and the following disclaimer in the documentation
							 | 
						|
								 *   and/or other materials provided with the distribution.
							 | 
						|
								 * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
							 | 
						|
								 *   any contributors may be used to endorse or promote products derived from
							 | 
						|
								 *   this software without specific prior written permission.
							 | 
						|
								 *
							 | 
						|
								 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
							 | 
						|
								 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
							 | 
						|
								 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
							 | 
						|
								 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
							 | 
						|
								 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
							 | 
						|
								 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
							 | 
						|
								 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
							 | 
						|
								 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
							 | 
						|
								 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
							 | 
						|
								 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
							 | 
						|
								 * POSSIBILITY OF SUCH DAMAGE.
							 | 
						|
								 *
							 | 
						|
								 * ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/** \file stlsoft/conversion/ptr_cast.hpp
							 | 
						|
								 *
							 | 
						|
								 * \brief [C++ only] Definition of the stlsoft::ptr_cast cast class
							 | 
						|
								 *   (\ref group__library__conversion "Conversion" Library).
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_PTR_CAST
							 | 
						|
								#define STLSOFT_INCL_STLSOFT_CONVERSION_HPP_PTR_CAST
							 | 
						|
								
							 | 
						|
								#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
							 | 
						|
								# define STLSOFT_VER_STLSOFT_CONVERSION_HPP_PTR_CAST_MAJOR      4
							 | 
						|
								# define STLSOFT_VER_STLSOFT_CONVERSION_HPP_PTR_CAST_MINOR      0
							 | 
						|
								# define STLSOFT_VER_STLSOFT_CONVERSION_HPP_PTR_CAST_REVISION   8
							 | 
						|
								# define STLSOFT_VER_STLSOFT_CONVERSION_HPP_PTR_CAST_EDIT       38
							 | 
						|
								#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Compatibility
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								/*
							 | 
						|
								[Incompatibilies-start]
							 | 
						|
								STLSOFT_COMPILER_IS_INTEL: _MSC_VER<1310
							 | 
						|
								STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1310
							 | 
						|
								STLSOFT_COMPILER_IS_WATCOM:
							 | 
						|
								[Incompatibilies-end]
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Includes
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
							 | 
						|
								# include <stlsoft/stlsoft.h>
							 | 
						|
								#endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
							 | 
						|
								#ifndef STLSOFT_INCL_STLSOFT_META_HPP_BASE_TYPE_TRAITS
							 | 
						|
								# include <stlsoft/meta/base_type_traits.hpp>
							 | 
						|
								#endif /* !STLSOFT_INCL_STLSOFT_META_HPP_BASE_TYPE_TRAITS */
							 | 
						|
								
							 | 
						|
								#ifndef STLSOFT_INCL_TYPEINFO
							 | 
						|
								# define STLSOFT_INCL_TYPEINFO
							 | 
						|
								# include <typeinfo>
							 | 
						|
								#endif /* !STLSOFT_INCL_TYPEINFO */
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Namespace
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#ifndef _STLSOFT_NO_NAMESPACE
							 | 
						|
								namespace stlsoft
							 | 
						|
								{
							 | 
						|
								#endif /* _STLSOFT_NO_NAMESPACE */
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Classes
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								/** \brief A cast that throws bad_cast for pointer cast failures, as well as
							 | 
						|
								 *   for reference casts.
							 | 
						|
								 *
							 | 
						|
								 * \ingroup group__library__conversion
							 | 
						|
								 *
							 | 
						|
								 * Assume the following class hierarchy, and variables:
							 | 
						|
								\code
							 | 
						|
								class Parent
							 | 
						|
								{
							 | 
						|
								public:
							 | 
						|
								  virtual ~Parent();
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								class A
							 | 
						|
								  : public Parent
							 | 
						|
								{
							 | 
						|
								public:
							 | 
						|
								  ~A();
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								class B
							 | 
						|
								  : public Parent
							 | 
						|
								{
							 | 
						|
								public:
							 | 
						|
								  ~B();
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								. . .
							 | 
						|
								
							 | 
						|
								A   a;
							 | 
						|
								B   b;
							 | 
						|
								\endcode
							 | 
						|
								 *
							 | 
						|
								 * The following code segments illustrate the similarities and differences
							 | 
						|
								 * between dynamic_cast and ptr_cast:
							 | 
						|
								 *
							 | 
						|
								 * (i) dynamic cast of reference that succeeds
							 | 
						|
								\code
							 | 
						|
								A   &ra1 = dynamic_cast<A&>(a);
							 | 
						|
								A   &ra2 = stlsoft::ptr_cast<A&>(a);
							 | 
						|
								
							 | 
						|
								assert(&ra1 == &ra2);
							 | 
						|
								\endcode
							 | 
						|
								 *
							 | 
						|
								 * (ii) dynamic cast of pointer that succeeds
							 | 
						|
								\code
							 | 
						|
								A   *pa = dynamic_cast<A*>(&a);
							 | 
						|
								
							 | 
						|
								assert(NULL != pa);
							 | 
						|
								assert(stlsoft::ptr_cast<A*>(&a) == pa);
							 | 
						|
								\endcode
							 | 
						|
								 *
							 | 
						|
								 * (iii) dynamic cast of reference that fails
							 | 
						|
								\code
							 | 
						|
								bool bCastFailed1 = false;
							 | 
						|
								
							 | 
						|
								try
							 | 
						|
								{
							 | 
						|
								  B &b1 = dynamic_cast<B&>(a);
							 | 
						|
								
							 | 
						|
								  . . . // Will never get here
							 | 
						|
								}
							 | 
						|
								catch(std::bad_cast &)
							 | 
						|
								{
							 | 
						|
								  bCastFailed1 = true;
							 | 
						|
								}
							 | 
						|
								assert(bCastFailed1);
							 | 
						|
								
							 | 
						|
								bool bCastFailed2 = false;
							 | 
						|
								
							 | 
						|
								try
							 | 
						|
								{
							 | 
						|
								  B &rb = stlsoft::ptr_cast<B&>(a);
							 | 
						|
								
							 | 
						|
								  . . . // Will never get here
							 | 
						|
								}
							 | 
						|
								catch(std::bad_cast &)
							 | 
						|
								{
							 | 
						|
								  bCastFailed2 = true;
							 | 
						|
								}
							 | 
						|
								assert(bCastFailed2);
							 | 
						|
								\endcode
							 | 
						|
								 *
							 | 
						|
								 * (iv) dynamic cast of pointer that fails
							 | 
						|
								\code
							 | 
						|
								assert(NULL == dynamic_cast<B*>(&a));
							 | 
						|
								
							 | 
						|
								bool bCastFailed = false;
							 | 
						|
								
							 | 
						|
								try
							 | 
						|
								{
							 | 
						|
								  B &rb = stlsoft::ptr_cast<B&>(&a);
							 | 
						|
								
							 | 
						|
								  . . . // Will never get here
							 | 
						|
								}
							 | 
						|
								catch(std::bad_cast &)
							 | 
						|
								{
							 | 
						|
								  bCastFailed = true;
							 | 
						|
								}
							 | 
						|
								assert(bCastFailed);
							 | 
						|
								\endcode
							 | 
						|
								 *
							 | 
						|
								 * \note This is described in detail in chapter 19 of
							 | 
						|
								 *  <a href = "http://www.imperfectcplusplus.com/">Imperfect C++</a>.
							 | 
						|
								 */
							 | 
						|
								template <ss_typename_param_k Target>
							 | 
						|
								struct ptr_cast
							 | 
						|
								{
							 | 
						|
								public:
							 | 
						|
								    /// The target type
							 | 
						|
								    typedef Target                                                          target_type;
							 | 
						|
								    /// The current instantiation of the type
							 | 
						|
								    typedef ptr_cast<Target>                                                class_type;
							 | 
						|
								    /// The target base type
							 | 
						|
								    typedef ss_typename_type_k stlsoft::base_type_traits<Target>::cv_type   target_base_type;
							 | 
						|
								    /// The reference type
							 | 
						|
								    typedef target_base_type&                                               reference_type;
							 | 
						|
								    /// The pointer type
							 | 
						|
								    typedef target_base_type*                                               pointer_type;
							 | 
						|
								
							 | 
						|
								private:
							 | 
						|
								    typedef ss_typename_type_k stlsoft::base_type_traits<Target>::base_type target_base_type_;
							 | 
						|
								    static target_base_type_* manage_const(target_base_type_* p)
							 | 
						|
								    {
							 | 
						|
								        return p;
							 | 
						|
								    }
							 | 
						|
								#if defined(STLSOFT_COMPILER_IS_BORLAND)
							 | 
						|
								    static target_base_type_* manage_const(target_base_type_ const* p)
							 | 
						|
								    {
							 | 
						|
								        return const_cast<target_base_type_*>(p);
							 | 
						|
								    }
							 | 
						|
								#else /* ? compiler */
							 | 
						|
								    static target_base_type_ const* manage_const(target_base_type_ const* p)
							 | 
						|
								    {
							 | 
						|
								        return p;
							 | 
						|
								    }
							 | 
						|
								#endif /* compiler */
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    /// Constructor used when casting a reference
							 | 
						|
								    template <ss_typename_param_k Source>
							 | 
						|
								    ptr_cast(Source &s)
							 | 
						|
								        : m_p(manage_const(&dynamic_cast<Target>(s)))
							 | 
						|
								    {
							 | 
						|
								        // Nothing to do: dynamic_cast throws for reference types
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /// Constructor used when casting a pointer
							 | 
						|
								    template <ss_typename_param_k Source>
							 | 
						|
								#if defined(STLSOFT_COMPILER_IS_BORLAND) || \
							 | 
						|
								    defined(STLSOFT_COMPILER_IS_GCC) || \
							 | 
						|
								    defined(STLSOFT_COMPILER_IS_MWERKS)
							 | 
						|
								    ptr_cast(Source*& s)
							 | 
						|
								#else /* ? compiler */
							 | 
						|
								    ptr_cast(Source* s)
							 | 
						|
								#endif /* compiler */
							 | 
						|
								        : m_p(manage_const(dynamic_cast<Target>(s)))
							 | 
						|
								    {
							 | 
						|
								        if(NULL == m_p)
							 | 
						|
								        {
							 | 
						|
								            STLSOFT_THROW_X(stlsoft_ns_qual_std(bad_cast)());
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
							 | 
						|
								    ptr_cast(pointer_type pt)
							 | 
						|
								        : m_p(pt)
							 | 
						|
								    {}
							 | 
						|
								    ptr_cast(reference_type t)
							 | 
						|
								        : m_p(&t)
							 | 
						|
								    {}
							 | 
						|
								#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
							 | 
						|
								
							 | 
						|
								public:
							 | 
						|
								    /// Converts an instance of the cast class to a reference
							 | 
						|
								    operator reference_type () const
							 | 
						|
								    {
							 | 
						|
								        return const_cast<reference_type>(*m_p);
							 | 
						|
								    }
							 | 
						|
								    /// Converts an instance of the cast class to a pointer
							 | 
						|
								    operator pointer_type () const
							 | 
						|
								    {
							 | 
						|
								        return const_cast<pointer_type>(m_p);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								private:
							 | 
						|
								    pointer_type  m_p;
							 | 
						|
								
							 | 
						|
								// Not to be implemented
							 | 
						|
								private:
							 | 
						|
								    ptr_cast(class_type const&);
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								////////////////////////////////////////////////////////////////////////////
							 | 
						|
								// Unit-testing
							 | 
						|
								
							 | 
						|
								#ifdef STLSOFT_UNITTEST
							 | 
						|
								# include "./unittest/ptr_cast_unittest_.h"
							 | 
						|
								#endif /* STLSOFT_UNITTEST */
							 | 
						|
								
							 | 
						|
								/* ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								#ifndef _STLSOFT_NO_NAMESPACE
							 | 
						|
								} // namespace stlsoft
							 | 
						|
								#endif /* _STLSOFT_NO_NAMESPACE */
							 | 
						|
								
							 | 
						|
								/* ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								#endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_PTR_CAST */
							 | 
						|
								
							 | 
						|
								/* ///////////////////////////// end of file //////////////////////////// */
							 |