// Filename: dcast.h // Created by: drose (06Aug01) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved // // All use of this software is subject to the terms of the Panda 3d // Software license. You should have received a copy of this license // along with this source code; you will also find a current copy of // the license at http://etc.cmu.edu/panda3d/docs/license/ . // // To contact the maintainers of this program write to // panda3d-general@lists.sourceforge.net . // //////////////////////////////////////////////////////////////////// #ifndef DCAST_H #define DCAST_H #include "pandabase.h" #include "typeHandle.h" #include "typedObject.h" // The DCAST (downcast) macro is defined as a convenience for // downcasting from some TypedObject pointer (or a PointerTo). It's // just a normal C++-style downcast, except it first checks get_type() // to make sure the downcasting is safe. If you compile with NDEBUG, // or set verify-dcast to #f, this check is removed. // DCAST will return NULL if the downcasting is unsafe. If you'd // rather it abort out of the function (a la nassertv/nassertr), then // see DCAST_INTO_V and DCAST_INTO_R, below. template INLINE WantType *_dcast(WantType *, TypedObject *ptr); template INLINE const WantType *_dcast(WantType *, const TypedObject *ptr); // Note: it is important that DCAST not repeat the pointer parameter, // since many users of DCAST may want to use the result of a function // as the pointer parameter, and it could be terribly confusing and // difficult to trace if the function were inadvertently executed // twice. This happened! #define DCAST(want_type, pointer) _dcast((want_type*)0, pointer) // DCAST_INTO_V and DCAST_INTO_R are similar in purpose to DCAST, // except they: (a) automatically assign a variable instead of // returning the downcasted pointer, and (b) they immediately return // out of the function if the downcasting fails. DCAST_INTO_V is for // use in a void function and returns nothing; DCAST_INTO_R is for use // in a non-void function and returns the indicated value. // Both DCAST_INTO_V and DCAST_INTO_R accept as the first parameter a // variable of type (want_type *) or (const want_type *), instead of // the name of the type. This variable will be filled with the new // pointer. // _dcast_ref is used to implement DCAST_INTO_V and DCAST_INTO_R. Its // difference from _dcast is that it takes a reference to a pointer as // a first parameter. The main point of this is to shut up the // compiler about pointers used before their value is assigned. template INLINE WantType *_dcast_ref(WantType *&, TypedObject *ptr); template INLINE const WantType *_dcast_ref(WantType *&, const TypedObject *ptr); #ifndef NDEBUG // _dcast_verify performs the actual verification. EXPCL_PANDAEXPRESS bool _dcast_verify(TypeHandle want_handle, size_t want_size, const TypedObject *ptr); #endif // NDEBUG #define DCAST_INTO_V(to_pointer, from_pointer) \ { \ (to_pointer) = _dcast_ref(to_pointer, from_pointer); \ nassertv((void *)(to_pointer) != (void *)NULL); \ } #define DCAST_INTO_R(to_pointer, from_pointer, return_value) \ { \ (to_pointer) = _dcast_ref(to_pointer, from_pointer); \ nassertr((void *)(to_pointer) != (void *)NULL, return_value); \ } #include "dcast.T" #endif