// @HEADER // *********************************************************************** // // Teuchos: Common Tools Package // Copyright (2004) Sandia Corporation // // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive // license for use of this work by or on behalf of the U.S. Government. // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA // Questions? Contact Michael A. Heroux (maherou@sandia.gov) // // *********************************************************************** // @HEADER #ifndef TEUCHOS_ARRAY_RCP_DECL_HPP #define TEUCHOS_ARRAY_RCP_DECL_HPP #include "Teuchos_RCP.hpp" namespace Teuchos { /** \brief Array reference-counted pointer class. * * This is a reference-counted class similar to RCP except * that it is designed to use reference counting to manage an array of objects * that use value semantics. Managing an array of objects is very different * from managing a pointer to an individual, possibly polymorphic, object. For * example, while implicit conversions from derived to base types is a good * thing when dealing with pointers to single objects, it is a very bad thing * when working with arrays of objects. Therefore, this class contains those * capabilities of raw pointers that are good dealing with arrays of objects * but excludes those that are bad, such as implicit conversions from derived * to base types. * * Note that all access will be checked at runtime to avoid reading invalid * memory if HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined which it is if * --enable-teuchos-abc is given to the configure script. * In order to be able to check access, every %ArrayRCP must * be constructed given a range. When HAVE_TEUCHOS_ARRAY_BOUNDSCHECK * is defined, this class simply does not give up a raw pointer or raw * reference to any internally referenced object if that object does not fall * with the range of valid data. * * ToDo: Finish documentation! * * \ingroup teuchos_mem_mng_grp */ template class ArrayRCP { public: //! @name Public types //@{ /** \brief . */ typedef T element_type; /** \brief. */ typedef Teuchos_Index Ordinal; #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK /** \brief . */ typedef ArrayRCP iterator; #else typedef T* iterator; #endif #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK /** \brief . */ typedef ArrayRCP const_iterator; #else typedef T* const_iterator; #endif //@} //! @name Constructors/Initializers //@{ /** \brief Initialize ArrayRCP to NULL. * * This allows clients to write code like: \code ArrayRCP p = null; \endcode * or \code ArrayRCP p; \endcode * and construct to NULL */ ArrayRCP( ENull null_arg = null ); /** \brief Initialize from another ArrayRCP object. * * After construction, this and r_ptr will * reference the same array. * * This form of the copy constructor is required even though the * below more general templated version is sufficient since some * compilers will generate this function automatically which will * give an incorrect implementation. * * Postconditions:
    *
  • this->get() == r_ptr.get() *
  • this->count() == r_ptr.count() *
  • this->has_ownership() == r_ptr.has_ownership() *
  • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 *
*/ ArrayRCP(const ArrayRCP& r_ptr); /** \brief Removes a reference to a dynamically allocated array and possibly deletes * the array if owned. * * Deallocates array if this->has_ownership() == true and * this->count() == 1. If this->count() == 1 but * this->has_ownership() == false then the array is not deleted * (usually using delete []). If this->count() > 1 then * the internal reference count shared by all the other related * ArrayRCP<...> objects for this shared array is * deincremented by one. If this->get() == NULL then nothing * happens. */ ~ArrayRCP(); /** \brief Copy the pointer to the referenced array and increment the * reference count. * * If this->has_ownership() == true and this->count() == 1 * before this operation is called, then the array will be deleted prior to * binding to the pointer (possibly NULL) pointed to in * r_ptr. Assignment to self (i.e. this->get() == * r_ptr.get()) is harmless and this function does nothing. * * Postconditions: *
    *
  • this->get() == r_ptr.get() *
  • this->count() == r_ptr.count() *
  • this->has_ownership() == r_ptr.has_ownership() *
  • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 *
*/ ArrayRCP& operator=(const ArrayRCP& r_ptr); //@} //! @name Object/Pointer Access Functions //@{ /** \brief Pointer (->) access to members of underlying object for * current position. * * Preconditions:
    *
  • this->get() != NULL *
  • this->lowerOffset() <= 0 *
  • this->upperOffset() >= 0 *
*/ T* operator->() const; /** \brief Dereference the underlying object for the current pointer * position. * * Preconditions:
    *
  • this->get() != NULL *
  • this->lowerOffset() <= 0 *
  • this->upperOffset() >= 0 *
*/ T& operator*() const; /** \brief Get the raw C++ pointer to the underlying object. * * Preconditions:
    *
  • [*this != null] this->lowerOffset() <= 0 *
  • [*this != null] this->upperOffset() >= 0 *
*/ T* get() const; /** \brief Random object access. * * Preconditions:
    *
  • this->get() != NULL *
  • this->lowerOffset() <= offset && offset <= this->upperOffset() *
*/ T& operator[](Ordinal offset) const; //@} //! @name Pointer Arithmetic Functions //@{ /** \brief Prefix increment of pointer (i.e. ++ptr). * * Does nothing if this->get() == NULL. * * Postconditions:
    *
  • [this->get()!=NULL] this->get() is incremented by 1 *
  • [this->get()!=NULL] this->lowerOffset() is deincremented by 1 *
  • [this->get()!=NULL] this->upperOffset() is deincremented by 1 *
*/ ArrayRCP& operator++(); /** \brief Postfix increment of pointer (i.e. ptr++). * * Does nothing if this->get() == NULL. * * Postconditions:
    *
  • this->get() is incremented by 1 *
  • this->lowerOffset() is deincremented by 1 *
  • this->upperOffset() is deincremented by 1 *
*/ ArrayRCP operator++(int); /** \brief Prefix deincrement of pointer (i.e. --ptr). * * Does nothing if this->get() == NULL. * * Postconditions:
    *
  • [this->get()!=NULL] this->get() is deincremented by 1 *
  • [this->get()!=NULL] this->lowerOffset() is incremented by 1 *
  • [this->get()!=NULL] this->upperOffset() is incremented by 1 *
*/ ArrayRCP& operator--(); /** \brief Postfix deincrement of pointer (i.e. ptr--). * * Does nothing if this->get() == NULL. * * Postconditions:
    *
  • this->get() is dincremented by 1 *
  • this->lowerOffset() is incremented by 1 *
  • this->upperOffset() is incremented by 1 *
*/ ArrayRCP operator--(int); /** \brief Pointer integer increment (i.e. ptr+=offset). * * Does nothing if this->get() == NULL. * * Postconditions:
    *
  • [this->get()!=NULL] this->get() is incremented by offset *
  • [this->get()!=NULL] this->lowerOffset() is deincremented by offset *
  • [this->get()!=NULL] this->upperOffset() is deincremented by offset *
*/ ArrayRCP& operator+=(Ordinal offset); /** \brief Pointer integer increment (i.e. ptr-=offset). * * Does nothing if this->get() == NULL. * * Postconditions:
    *
  • [this->get()!=NULL] this->get() is deincremented by offset *
  • [this->get()!=NULL] this->lowerOffset() is incremented by offset *
  • [this->get()!=NULL] this->upperOffset() is incremented by offset *
*/ ArrayRCP& operator-=(Ordinal offset); /** \brief Pointer integer increment (i.e. ptr+offset). * * Returns a null pointer if this->get() == NULL. * * Postconditions:
    *
  • [this->get()!=NULL] return->get() == this->get() + offset *
  • [this->get()!=NULL] return->lowerOffset() == this->lowerOffset() - offset *
  • [this->get()!=NULL] return->upperOffset() == this->upperOffset() - offset *
* * Note that since implicit conversion of ArrayRCP * objects is not allowed that it does not help at all to make this function * into a non-member function. */ ArrayRCP operator+(Ordinal offset) const; /** \brief Pointer integer deincrement (i.e. ptr-offset). * * Returns a null pointer if this->get() == NULL. * * Postconditions:
    *
  • [this->get()!=NULL] return->get() == this->get() - offset *
  • [this->get()!=NULL] return->lowerOffset() == this->lowerOffset() + offset *
  • [this->get()!=NULL] return->upperOffset() == this->upperOffset() + offset *
* * Note that since implicit conversion of ArrayRCP * objects is not allowed that it does not help at all to make this function * into a non-member function. */ ArrayRCP operator-(Ordinal offset) const; //@} //! @name Views //@{ /** \brief Return object for only const access to data. * * This function should only compile successfully if the type T is * not already declared const! */ ArrayRCP getConst() const; /** \brief Return a view of a contiguous range of elements. * * Preconditions:
    *
  • this->get() != NULL *
  • this->lowerOffset() <= lowerOffset *
  • lowerOffset + size - 1 <= this->upperOffset() *
* * Postconditions:
    *
  • return->get() == this->get() + lowerOffset *
  • return->lowerOffset() == 0 *
  • return->upperOffset() == size-1 *
*/ ArrayRCP subview( Ordinal lowerOffset, Ordinal size ) const; //@} //! @name General query functions //@{ /** \brief Return the number of ArrayRCP<> objects that have a reference * to the underlying pointer that is being shared. * * @return If this->get() == NULL then this function returns 0. * Otherwise, this function returns > 0. */ int count() const; /** \brief Returns true if the smart pointers share the same underlying reference-counted object. * * This method does more than just check if this->get() == r_ptr.get(). * It also checks to see if the underlying reference counting machinery is the * same. */ template bool shares_resource(const ArrayRCP& r_ptr) const; /** \brief Return the lower offset to valid data. */ Ordinal lowerOffset() const; /** \brief Return the upper offset to valid data. */ Ordinal upperOffset() const; /** \brief The total number of items in the managed array * (i.e. upperOffset()-lowerOffset()+1). */ Ordinal size() const; //@} //! @name Standard Container-Like Functions //@{ /** \brief Return an iterator to beginning of the array of data. * * If HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined then the iterator * returned is an ArrayRCP object and all operations are * checked at runtime. When HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is not * defined, the a raw pointer T* is returned for fast execution. * * Postconditions:
    *
  • [this->get()!=NULL] &*return == this->get() *
  • [this->get()==NULL] return == (null or NULL) *
*/ const_iterator begin() const; /** \brief Return an iterator to past the end of the array of data. * * If HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined then the iterator * returned is an ArrayRCP object and all operations are * checked at runtime. When HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is not * defined, the a raw pointer T* is returned for fast execution. * * Postconditions:
    *
  • [this->get()!=NULL] &*end == this->get()+(this->upperOffset()+1) *
  • [this->get()==NULL] return == (null or NULL) *
*/ const_iterator end() const; //@} //! @name Ownership //@{ /** \brief Release the ownership of the underlying array. * * After this function is called then the client is responsible for deleting * the returned pointer no matter how many ref_count_ptr objects * have a reference to it. If this->get() == NULL, then * this call is meaningless. * * Note that this function does not have the exact same semantics as does * auto_ptr::release(). In auto_ptr::release(), * this is set to NULL while here in ArrayRCP:: * release() only an ownership flag is set and this still points to * the same array. It would be difficult to duplicate the behavior of * auto_ptr::release() for this class. * * Postconditions:
    *
  • this->has_ownership() == false *
* * @return Returns the value of this->get() */ T* release(); /** \brief Give this and other ArrayRCP<> objects * ownership of the underlying referenced array to delete it. * * See ~ArrayRCP() above. This function does nothing if * this->get() == NULL. * * Postconditions:
    *
  • If this->get() == NULL then *
      *
    • this->has_ownership() == false (always!). *
    *
  • else *
      *
    • this->has_ownership() == true *
    *
*/ void set_has_ownership(); /** \brief Returns true if this has ownership of object pointed to * by this->get() in order to delete it. * * See ~ArrayRCP() above. * * \return If this->get() == NULL then this function always returns * false. Otherwise the value returned from this function depends * on which function was called most recently, if any; * set_has_ownership() (true) or release() * (false). */ bool has_ownership() const; //@} //! @name Assertion Functions. //@{ /** \brief Throws std::logic_error if this->get()==NULL, * otherwise returns reference to *this. */ const ArrayRCP& assert_not_null() const; /** \brief Throws std::logic_error if this->get()==NULL * orthis->get()!=NULL && (lowerOffset < this->lowerOffset() || * this->upperOffset() < upperOffset, otherwise returns reference to * *this */ const ArrayRCP& assert_in_range( Ordinal lowerOffset, Ordinal size ) const; //@} public: // Bad bad bad // ////////////////////////////////////// // Private types typedef PrivateUtilityPack::RCP_node node_t; private: // ////////////////////////////////////////////////////////////// // Private data members T *ptr_; // NULL if this pointer is null node_t *node_; // NULL if this pointer is null Ordinal lowerOffset_; Ordinal upperOffset_; public: #ifndef DOXYGEN_COMPILE // These constructors should be private but I have not had good luck making // this portable (i.e. using friendship etc.) in the past ArrayRCP( T* p, Ordinal lowerOffset, Ordinal upperOffset, bool has_ownership ); template ArrayRCP( T* p, Ordinal lowerOffset, Ordinal upperOffset, Dealloc_T dealloc, bool has_ownership ); // This is a very bad breach of encapsulation that is needed since MS VC++ 5.0 will // not allow me to declare template functions as friends. ArrayRCP( T* p, Ordinal lowerOffset, Ordinal upperOffset, node_t* node); T*& access_ptr(); T* access_ptr() const; // No preconditions node_t*& access_node(); node_t* access_node() const; #endif }; // end class ArrayRCP<...> /** \brief Traits specialization. * * \relates ArrayRCP */ template class TypeNameTraits > { public: static std::string name() { return "ArrayRCP<"+TypeNameTraits::name()+">"; } }; /** \brief Wraps a preallocated array of data with the assumption to call the * array version of delete. * * \relates ArrayRCP */ template ArrayRCP arcp( T* p, typename ArrayRCP::Ordinal lowerOffset ,typename ArrayRCP::Ordinal size , bool owns_mem = true ); /** \brief Wraps a preallocated array of data and uses a templated * deallocation strategy object to define deletion . * * \relates ArrayRCP */ template ArrayRCP arcp( T* p, typename ArrayRCP::Ordinal lowerOffset ,typename ArrayRCP::Ordinal size , Dealloc_T dealloc, bool owns_mem ); /** \brief Allocate a new array just given a dimension. * * Warning! The memory is allocated using new T[size] and is * *not* initialized (unless there is a default constructor for a user-defined * type). * * \relates ArrayRCP */ template ArrayRCP arcp( typename ArrayRCP::Ordinal size ); /** \brief Wrap an std::vector object as an * ArrayRCP object. * * \relates ArrayRCP */ template ArrayRCP arcp( const RCP > &v ); /** \brief Wrap a const std::vector object as an * ArrayRCP object. * * \relates ArrayRCP */ template ArrayRCP arcp( const RCP > &v ); /** \brief Get an std::vector object out of an * ArrayRCP object that was created using the * arcp() above to wrap the std::vector in the first place.. * * \relates ArrayRCP */ template RCP > get_std_vector( const ArrayRCP &ptr ); /** \brief Get a const std::vector object out of an * ArrayRCP object that was created using the * arcp() above to wrap the std::vector in the first place. * * \relates ArrayRCP */ template RCP > get_std_vector( const ArrayRCP &ptr ); /** \brief Returns true if p.get()==NULL. * * \relates ArrayRCP */ template bool is_null( const ArrayRCP &p ); /** \brief Returns true if p.get()==NULL. * * \relates ArrayRCP */ template bool operator==( const ArrayRCP &p, ENull ); /** \brief Returns true if p.get()!=NULL. * * \relates ArrayRCP */ template bool operator!=( const ArrayRCP &p, ENull ); /** \brief . * * \relates ArrayRCP */ template bool operator==( const ArrayRCP &p1, const ArrayRCP &p2 ); /** \brief . * * \relates ArrayRCP */ template bool operator!=( const ArrayRCP &p1, const ArrayRCP &p2 ); /** \brief . * * \relates ArrayRCP */ template bool operator<( const ArrayRCP &p1, const ArrayRCP &p2 ); /** \brief . * * \relates ArrayRCP */ template bool operator<=( const ArrayRCP &p1, const ArrayRCP &p2 ); /** \brief . * * \relates ArrayRCP */ template bool operator>( const ArrayRCP &p1, const ArrayRCP &p2 ); /** \brief . * * \relates ArrayRCP */ template bool operator>=( const ArrayRCP &p1, const ArrayRCP &p2 ); /** \brief Reinterpret cast of underlying ArrayRCP type from * T1* to T2*. * * The function will compile only if (reinterpret_cast(p1.get());) compiles. * * Warning! Do not use this function unless you absolutely know what * you are doing. Doing a reinterpret cast is always a tricking thing and * must only be done by developers who are 100% comfortable with what they are * doing. * * \relates ArrayRCP */ template ArrayRCP arcp_reinterpret_cast(const ArrayRCP& p1); /** \brief Implicit case the underlying ArrayRCP type from * T1* to T2*. * * The function will compile only if (T2 *p = p1.get();) compiles. * * Warning! Do not use this function unless you absolutely know what you * are doing. While implicit casting of pointers to single objects is usually * 100% safe, implicit casting pointers to arrays of objects can be very * dangerous. One std::exception that is always safe is when you are implicit * casting an array of pointers to non-const objects to an array of const * pointers to const objects. For example, the following implicit conversion * from a array pointer objects aptr1 of type * ArrayRCP to \code ArrayRCP aptr2 = arcp_implicit_cast(ptr1); \endcode * is always legal and safe to do. * * \relates ArrayRCP */ template ArrayRCP arcp_implicit_cast(const ArrayRCP& p1); /** \brief Set extra data associated with a ArrayRCP object. * * @param extra_data * [in] Data object that will be set (copied) * @param name [in] The name given to the extra data. The value of * name together with the data type T1 of the * extra data must be unique from any other such data or * the other data will be overwritten. * @param p [out] On output, will be updated with the input extra_data * @param destroy_when * [in] Determines when extra_data will be destroyed * in relation to the underlying reference-counted object. * If destroy_when==PRE_DESTROY then extra_data * will be deleted before the underlying reference-counted object. * If destroy_when==POST_DESTROY (the default) then extra_data * will be deleted after the underlying reference-counted object. * @param force_unique * [in] Determines if this type and name pair must be unique * in which case if an object with this same type and name * already exists, then an std::exception will be thrown. * The default is true for safety. * * If there is a call to this function with the same type of extra * data T1 and same arguments p and name * has already been made, then the current piece of extra data already * set will be overwritten with extra_data. However, if the * type of the extra data T1 is different, then the extra * data can be added and not overwrite existing extra data. This * means that extra data is keyed on both the type and name. This * helps to minimize the chance that clients will unexpectedly * overwrite data by accident. * * When the last RefcountPtr object is removed and the * reference-count node is deleted, then objects are deleted in the following * order: (1) All of the extra data that where added with * destroy_when==PRE_DESTROY are first, (2) then the underlying * reference-counted object is deleted, and (3) the rest of the extra data * that was added with destroy_when==PRE_DESTROY is then deleted. * The order in which the objects are destroyed is not guaranteed. Therefore, * clients should be careful not to add extra data that has deletion * dependencies (instead consider using nested ArrayRCP objects as extra * data which will guarantee the order of deletion). * * Preconditions:
    *
  • p->get() != NULL (throws std::logic_error) *
  • If this function has already been called with the same template * type T1 for extra_data and the same std::string name * and force_unique==true, then an std::invalid_argument * std::exception will be thrown. *
* * Note, this function is made a non-member function to be consistent * with the non-member get_extra_data() functions. * * \relates ArrayRCP */ template void set_extra_data( const T1 &extra_data, const std::string& name, ArrayRCP *p ,EPrePostDestruction destroy_when #ifndef __sun = POST_DESTROY #endif ,bool force_unique #ifndef __sun = true #endif ); #ifdef __sun template inline void set_extra_data( const T1 &extra_data, const std::string& name, ArrayRCP *p ) { set_extra_data( extra_data, name, p, POST_DESTROY, true ); } template inline void set_extra_data( const T1 &extra_data, const std::string& name, ArrayRCP *p, EPrePostDestruction destroy_when ) { set_extra_data( extra_data, name, p, destroy_when, true ); } #endif /** \brief Get a non-const reference to extra data associated with a ArrayRCP object. * * @param p [in] Smart pointer object that extra data is being extracted from. * @param name [in] Name of the extra data. * * @return Returns a non-const reference to the extra_data object. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
  • name and T1 must have been used in a previous * call to set_extra_data() (throws std::invalid_argument). *
* * Note, this function must be a non-member function since the client * must manually select the first template argument. * * \relates ArrayRCP */ template T1& get_extra_data( ArrayRCP& p, const std::string& name ); /** \brief Get a const reference to extra data associated with a ArrayRCP object. * * @param p [in] Smart pointer object that extra data is being extracted from. * @param name [in] Name of the extra data. * * @return Returns a const reference to the extra_data object. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
  • name and T1 must have been used in a previous * call to set_extra_data() (throws std::invalid_argument). *
* * Note, this function must be a non-member function since the client * must manually select the first template argument. * * Also note that this const version is a false sense of security * since a client can always copy a const ArrayRCP object * into a non-const object and then use the non-const version to * change the data. However, its presence will help to avoid some * types of accidental changes to this extra data. * * \relates ArrayRCP */ template const T1& get_extra_data( const ArrayRCP& p, const std::string& name ); /** \brief Get a pointer to non-const extra data (if it exists) associated * with a ArrayRCP object. * * @param p [in] Smart pointer object that extra data is being extracted from. * @param name [in] Name of the extra data. * * @return Returns a non-const pointer to the extra_data object. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
* * Postconditions:
    *
  • If name and T1 have been used in a previous * call to set_extra_data() then return !=NULL * and otherwise return == NULL. *
* * Note, this function must be a non-member function since the client * must manually select the first template argument. * * \relates ArrayRCP */ template T1* get_optional_extra_data( ArrayRCP& p, const std::string& name ); /** \brief Get a pointer to const extra data (if it exists) associated with a ArrayRCP object. * * @param p [in] Smart pointer object that extra data is being extracted from. * @param name [in] Name of the extra data. * * @return Returns a const pointer to the extra_data object if it exists. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
* * Postconditions:
    *
  • If name and T1 have been used in a previous * call to set_extra_data() then return !=NULL * and otherwise return == NULL. *
* * Note, this function must be a non-member function since the client * must manually select the first template argument. * * Also note that this const version is a false sense of security * since a client can always copy a const ArrayRCP object * into a non-const object and then use the non-const version to * change the data. However, its presence will help to avoid some * types of accidental changes to this extra data. * * \relates ArrayRCP */ template const T1* get_optional_extra_data( const ArrayRCP& p, const std::string& name ); /** \brief Return a non-const reference to the underlying deallocator object. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
  • The deallocator object type used to construct p is same as Dealloc_T * (throws std::logic_error) *
* * \relates ArrayRCP */ template Dealloc_T& get_dealloc( ArrayRCP& p ); /** \brief Return a const reference to the underlying deallocator object. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
  • The deallocator object type used to construct p is same as Dealloc_T * (throws std::logic_error) *
* * Note that the const version of this function provides only * a very ineffective attempt to avoid accidental changes to the * deallocation object. A client can always just create a new * non-const ArrayRCP object from any * const ArrayRCP object and then call the * non-const version of this function. * * \relates ArrayRCP */ template const Dealloc_T& get_dealloc( const ArrayRCP& p ); /** \brief Return a pointer to the underlying non-const deallocator * object if it exists. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
* * Postconditions:
    *
  • If the deallocator object type used to construct p is same as Dealloc_T * then return!=NULL, otherwise return==NULL *
* * \relates ArrayRCP */ template Dealloc_T* get_optional_dealloc( ArrayRCP& p ); /** \brief Return a pointer to the underlying const deallocator * object if it exists. * * Preconditions:
    *
  • p.get() != NULL (throws std::logic_error) *
* * Postconditions:
    *
  • If the deallocator object type used to construct p is same as Dealloc_T * then return!=NULL, otherwise return==NULL *
* * Note that the const version of this function provides only * a very ineffective attempt to avoid accidental changes to the * deallocation object. A client can always just create a new * non-const ArrayRCP object from any * const ArrayRCP object and then call the * non-const version of this function. * * \relates ArrayRCP */ template const Dealloc_T* get_optional_dealloc( const ArrayRCP& p ); /** \brief Output stream inserter. * * The implementation of this function just print pointer addresses and * therefore puts not restrictions on the data types involved. * * \relates ArrayRCP */ template std::ostream& operator<<( std::ostream& out, const ArrayRCP& p ); } // end namespace Teuchos #endif // TEUCHOS_ARRAY_RCP_DECL_HPP