00001 // Filename: dcast.h 00002 // Created by: drose (06Aug01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef DCAST_H 00016 #define DCAST_H 00017 00018 #include "pandabase.h" 00019 00020 #include "typeHandle.h" 00021 #include "typedObject.h" 00022 #include "config_express.h" 00023 00024 // The DCAST (downcast) macro is defined as a convenience for 00025 // downcasting from some TypedObject pointer (or a PointerTo). It's 00026 // just a normal C++-style downcast, except it first checks get_type() 00027 // to make sure the downcasting is safe. If you compile with NDEBUG, 00028 // or set verify-dcast to #f, this check is removed. 00029 00030 // DCAST will return NULL if the downcasting is unsafe. If you'd 00031 // rather it abort out of the function (a la nassertv/nassertr), then 00032 // see DCAST_INTO_V and DCAST_INTO_R, below. 00033 00034 template<class WantType> 00035 INLINE WantType *_dcast(WantType *, TypedObject *ptr); 00036 template<class WantType> 00037 INLINE const WantType *_dcast(WantType *, const TypedObject *ptr); 00038 00039 // Note: it is important that DCAST not repeat the pointer parameter, 00040 // since many users of DCAST may want to use the result of a function 00041 // as the pointer parameter, and it could be terribly confusing and 00042 // difficult to trace if the function were inadvertently executed 00043 // twice. This happened! 00044 #define DCAST(want_type, pointer) _dcast((want_type*)0, pointer) 00045 00046 // DCAST_INTO_V and DCAST_INTO_R are similar in purpose to DCAST, 00047 // except they: (a) automatically assign a variable instead of 00048 // returning the downcasted pointer, and (b) they immediately return 00049 // out of the function if the downcasting fails. DCAST_INTO_V is for 00050 // use in a void function and returns nothing; DCAST_INTO_R is for use 00051 // in a non-void function and returns the indicated value. 00052 00053 // Both DCAST_INTO_V and DCAST_INTO_R accept as the first parameter a 00054 // variable of type (want_type *) or (const want_type *), instead of 00055 // the name of the type. This variable will be filled with the new 00056 // pointer. 00057 00058 00059 // _dcast_ref is used to implement DCAST_INTO_V and DCAST_INTO_R. Its 00060 // difference from _dcast is that it takes a reference to a pointer as 00061 // a first parameter. The main point of this is to shut up the 00062 // compiler about pointers used before their value is assigned. 00063 template<class WantType> 00064 INLINE WantType *_dcast_ref(WantType *&, TypedObject *ptr); 00065 template<class WantType> 00066 INLINE const WantType *_dcast_ref(WantType *&, const TypedObject *ptr); 00067 00068 #ifdef DO_DCAST 00069 // _dcast_verify performs the actual verification. 00070 EXPCL_PANDAEXPRESS bool 00071 _dcast_verify(TypeHandle want_handle, size_t want_size, 00072 const TypedObject *ptr); 00073 #endif // DO_DCAST 00074 00075 #define DCAST_INTO_V(to_pointer, from_pointer) \ 00076 { \ 00077 (to_pointer) = _dcast_ref(to_pointer, from_pointer); \ 00078 nassertv((void *)(to_pointer) != (void *)NULL); \ 00079 } 00080 00081 #define DCAST_INTO_R(to_pointer, from_pointer, return_value) \ 00082 { \ 00083 (to_pointer) = _dcast_ref(to_pointer, from_pointer); \ 00084 nassertr((void *)(to_pointer) != (void *)NULL, return_value); \ 00085 } 00086 00087 #include "dcast.T" 00088 00089 #endif