libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dynamic_cast.hpp
Go to the documentation of this file.
1 #ifndef LIBJMMCG_CORE_DYNAMIC_CAST_HPP
2 #define LIBJMMCG_CORE_DYNAMIC_CAST_HPP
3 /******************************************************************************
4 ** Copyright © 2002 by J.M.McGuiness, coder@hussar.me.uk
5 **
6 ** This library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Lesser General Public
8 ** License as published by the Free Software Foundation; either
9 ** version 2.1 of the License, or (at your option) any later version.
10 **
11 ** This library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** Lesser General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public
17 ** License along with this library; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 
21 #include "exception.hpp"
22 
23 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
24 
25  /**
26  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:
27 
28  1. The class types cast from and to.
29  2. The address of the object on which the cast was attempted.
30  3. The file and line of where the check was done. (So you can more easily track down the errors!)
31  4. Extra potentially handy info.
32  */
33  template<
34  typename To,
35  class Excpt=crt_exception<ppd::platform_api, ppd::heavyweight_threading> ///< Re-throw an exception_type derived from this type and std::bad_cast.
36  >
38  typedef To result_type;
39  /**
40  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.
41 
42  \see std::bad_cast
43  */
44  struct exception_type : virtual public Excpt, public std::bad_cast {
45  __stdcall exception_type(const tstring &r, const info::function &f, const info::revision &ri)
46  : Excpt(r, f, ri) {}
47  };
48 
49  template<typename From> result_type &
50  operator()(From &obj, const unsigned long l, const char *fun_name, const char *file) noexcept(false) {
51  try {
52  return dynamic_cast<result_type &>(obj);
53  } catch (std::bad_cast const &e) {
54  info::function fun(
55  l,
56  fun_name,
58  info::function::argument(_T("C++ RTTI type to cast from."), exception_type::thread_traits::demangle_name(typeid(From)))
59  );
60  fun.add_arg(info::function::argument(_T("C++ RTTI type to cast to."), exception_type::thread_traits::demangle_name(typeid(result_type))));
61  tostringstream ss;
62  ss<<_T("0x")<<&obj;
63  fun.add_arg(info::function::argument(_T("Address of object being cast."), ss.str()));
65  }
66  }
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::LIBJMMCG_VER_NAMESPACE::checked_dynamic_cast<To>()((obj), __LINE__, __PRETTY_FUNCTION__, __FILE__)
74 
75 #endif