root/core/dynamic_cast.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


   1 #ifndef libjmmcg_core_dynamic_cast_hpp
   2 #define libjmmcg_core_dynamic_cast_hpp
   3 /******************************************************************************
   4 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/dynamic_cast.hpp 2055 2017-05-13 19:35:47Z jmmcg $
   5 **
   6 ** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
   7 **
   8 ** This library is free software; you can redistribute it and/or
   9 ** modify it under the terms of the GNU Lesser General Public
  10 ** License as published by the Free Software Foundation; either
  11 ** version 2.1 of the License, or (at your option) any later version.
  12 **
  13 ** This library is distributed in the hope that it will be useful,
  14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16 ** Lesser General Public License for more details.
  17 **
  18 ** You should have received a copy of the GNU Lesser General Public
  19 ** License along with this library; if not, write to the Free Software
  20 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21 */
  22 
  23 #include"exception.hpp"
  24 
  25 namespace jmmcg {
  26 
  27         /**
  28                 The purpose of this class is to give an opportunity to programmers to replace the useless "std::bad_cast" thrown when performing a "dynamic_cast<To &>(obj)". This class will catch the exception, wrap it up with lots more info, then re-throw an exception_type derived from Excpt and std::bad_cast. For example it will give:
  29 
  30                 1. The class types cast from and to.
  31                 2. The address of the object on which the cast was attempted.
  32                 3. The file and line of where the check was done. (So you can more easily track down the errors!)
  33                 4. Extra potentially handy info.
  34         */
  35         template<
  36                 typename To,
  37                 class Excpt=jmmcg::crt_exception<jmmcg::ppd::platform_api, jmmcg::ppd::heavyweight_threading>   ///< Re-throw an exception_type derived from this type and std::bad_cast.
  38         >
  39         struct checked_dynamic_cast {
  40                 typedef To result_type;
  41                 /**
  42                         So that you can still catch this type with your unaltered catches of std::bad_cast, but better to alter them so that you can get at the greater info that is provided.
  43 
  44                         \see std::bad_cast
  45                 */
  46                 struct exception_type : virtual public Excpt, public std::bad_cast {
  47                         __stdcall exception_type(const tstring &r, const info::function &f, const info::revision &ri)
  48                         : Excpt(r, f, ri) {}
  49                 };
  50 
  51                 template<typename From> result_type &
  52                 operator()(From &obj, const unsigned long l, const char *fun_name, const char *file) noexcept(false) {
  53                         try {
  54                                 return dynamic_cast<result_type &>(obj);
  55                         } catch (std::bad_cast const &e) {
  56                                 jmmcg::info::function fun(
  57                                         l,
  58                                         fun_name,
  59                                         typeid(jmmcg::checked_dynamic_cast<result_type, exception_type>),
  60                                         jmmcg::info::function::argument(_T("C++ RTTI type to cast from."), typeid(From).name())
  61                                 );
  62                                 fun.add_arg(jmmcg::info::function::argument(_T("C++ RTTI type to cast to."), typeid(result_type).name()));
  63                                 jmmcg::tostringstream ss;
  64                                 ss<<_T("0x")<<&obj;
  65                                 fun.add_arg(jmmcg::info::function::argument(_T("Address of object being cast."), ss.str()));
  66                                 throw exception_type(e.what(), fun, jmmcg::info::revision(_T("$Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/dynamic_cast.hpp 2055 2017-05-13 19:35:47Z jmmcg $"), file));
  67                         }
  68                 }
  69         };
  70 
  71 /// Use the macro "JMMCG_CHK_DYNAMIC_CAST(To, obj)" as your drop-in replacement for where you'd place statements like: "To &a=dynamic_cast<To>(obj);". Note that this macro cannot replace expression forms.
  72 #       define CHK_DYNAMIC_CAST(To, obj) \
  73         jmmcg::checked_dynamic_cast<To>()((obj), __LINE__, __PRETTY_FUNCTION__, __FILE__)
  74 
  75 }
  76 
  77 #endif

/* [<][>][^][v][top][bottom][index][help] */