1 // boost polymorphic_pointer_cast.hpp header file ----------------------------------------------// 2 // (C) Copyright Boris Rasin and Antony Polukhin 2014-2019. 3 // Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 // See http://www.boost.org/libs/conversion for Documentation. 8 9 #ifndef BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP 10 #define BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP 11 12 # include <boost/config.hpp> 13 # include <boost/assert.hpp> 14 # include <boost/pointer_cast.hpp> 15 # include <boost/throw_exception.hpp> 16 # include <boost/utility/declval.hpp> 17 # ifdef BOOST_NO_CXX11_DECLTYPE 18 # include <boost/typeof/typeof.hpp> 19 # endif 20 21 #ifdef BOOST_HAS_PRAGMA_ONCE 22 # pragma once 23 #endif 24 25 namespace boost 26 { 27 // See the documentation for descriptions of how to choose between 28 // static_pointer_cast<>, dynamic_pointer_cast<>, polymorphic_pointer_cast<> and polymorphic_pointer_downcast<> 29 30 // polymorphic_pointer_downcast --------------------------------------------// 31 32 // BOOST_ASSERT() checked polymorphic downcast. Crosscasts prohibited. 33 // Supports any type with static_pointer_cast/dynamic_pointer_cast functions: 34 // built-in pointers, std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr, etc. 35 36 // WARNING: Because this cast uses BOOST_ASSERT(), it violates 37 // the One Definition Rule if used in multiple translation units 38 // where BOOST_DISABLE_ASSERTS, BOOST_ENABLE_ASSERT_HANDLER 39 // NDEBUG are defined inconsistently. 40 41 // Contributed by Boris Rasin 42 43 namespace detail 44 { 45 template <typename Target, typename Source> 46 struct dynamic_pointer_cast_result 47 { 48 #ifdef BOOST_NO_CXX11_DECLTYPE 49 BOOST_TYPEOF_NESTED_TYPEDEF_TPL(nested, dynamic_pointer_cast<Target>(boost::declval<Source>())) 50 typedef typename nested::type type; 51 #else 52 typedef decltype(dynamic_pointer_cast<Target>(boost::declval<Source>())) type; 53 #endif 54 }; 55 } 56 57 template <typename Target, typename Source> 58 inline typename detail::dynamic_pointer_cast_result<Target, Source>::type polymorphic_pointer_downcast(const Source & x)59 polymorphic_pointer_downcast (const Source& x) 60 { 61 BOOST_ASSERT(dynamic_pointer_cast<Target> (x) == x); 62 return static_pointer_cast<Target> (x); 63 } 64 65 template <typename Target, typename Source> 66 inline typename detail::dynamic_pointer_cast_result<Target, Source>::type polymorphic_pointer_cast(const Source & x)67 polymorphic_pointer_cast (const Source& x) 68 { 69 typename detail::dynamic_pointer_cast_result<Target, Source>::type tmp 70 = dynamic_pointer_cast<Target> (x); 71 if ( !tmp ) boost::throw_exception( std::bad_cast() ); 72 73 return tmp; 74 } 75 76 } // namespace boost 77 78 #endif // BOOST_CONVERSION_POLYMORPHIC_POINTER_CAST_HPP 79