// @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