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