// @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_ABSTRACT_FACTORY_STD_HPP
#define TEUCHOS_ABSTRACT_FACTORY_STD_HPP
#include "Teuchos_AbstractFactory.hpp"
namespace Teuchos {
/** \brief Default post-modification policy class for
* AbstractFactorStd which does nothing!
*/
template
class PostModNothing {
public:
/** \brief . */
void initialize(T_impl* p) const {} // required!
};
/** \brief Default allocation policy class for
* AbstractFactoryStd which returns new T_impl().
*/
template
class AllocatorNew {
public:
/** \brief . */
typedef Teuchos::RCP ptr_t; // required!
/** \brief . */
const ptr_t allocate() const { return Teuchos::rcp(new T_impl()); } // required!
};
/** \brief Simple, templated concrete subclass of universal "Abstract
* Factory" interface for the creation of objects.
*
* This concrete subclass represents a general
* AbstractFactory subclass that can be modified through
* policy template parameters. This class is templated on the
* interface type T_itfc that is exposed by the
* AbstractFactory base interface and by a (concrete)
* implementation type T_impl. The most typical use of this
* subclass is to use a concrete, default-constructable subclass for
* T_impl and then to simply instantiate a concrete abstract
* factory for that class using:
\verbatim
Teuchos::AbstractFactoryStd abstractFactory;
\endverbatim
*
* For this default usage, The only requirements for the derived classes type
* T_impl is that it allow the default constructor
* T_impl::T_impl() (i.e. dont make T_impl::T_impl()
* private) and that it allow T_impl::new() and
* T_impl::delete (i.e. don't make them private functions, see
* Meyers, More Effective C++, Item 27).
* However, this subclass is also templated on two other policy types that
* allow a modification on how objects are created and destroyed. The first
* templated policy type, T_PostMod, defines how an object is
* modified after it is initially created. The second templated policy type,
* T_Allocator, defines exactly how an object is created (and
* therefore also how it is destroyed). These type two policy classes are
* described in more detail below.
*
* The type T_PostMod is responsible for performing any post
* modifications on a dynamically allocated object before returning it from
* create(). The requirements for the type T_PostMod are
* that it has a default constructor, a copy constructor and a method
* T_PostMod::initialize(T_itfc2*) const that will perform any
* required post modifications (initializations). The type T_itfc2
* argument for this function must be a base class of T_impl of
* course. The default type for T_PostMod is
* PostModNothing which does nothing.
*
* The type T_Allocator allows for specialized memory allocation and
* cleanup. This type must allow the default constructor and copy constructor
* and have a method Teuchos::RCP T_Allocator::allocate()
* const which creates a smart reference-counted pointer to the allocated
* object. Also, in returning a RCP<> object, the client can
* set a deallocatioin policy object that can specialize the deallocation of
* the object (see RCP). In defining a specialized
* T_Allocator class, the client can all initialize the object using
* more than just the default constructor. Therefore, if the client provides
* a specialized T_Allocator class, there are no restrictions on the
* class T_impl (i.e. does not have to have a default constructor or
* allow new or delete). The default class for
* T_Allocator is AllocatorNew who's
* allocate() function just returns rcp(new T_impl()).
*
* Since the T_Allocator class can specialize both the memory
* management and can initialize the object using more that the default
* constructor, the class T_PostMod may seem unecessary. However, it
* is more likely that the client will want to define an initialization for a
* set of classes through an abstract interface and can not for a particular
* concrete subclass. Also the initialization for an object can be orthogonal
* to how it is created and destroyed, thus the two classes T_PostMod
* and T_Allocator are both needed for a more general implementation.
*/
template
,class T_Allocator = AllocatorNew
>
class AbstractFactoryStd : public AbstractFactory {
public:
typedef typename Teuchos::AbstractFactory::obj_ptr_t obj_ptr_t; // RAB: 20030916: G++ 3.2 complains without this
/** \brief . */
AbstractFactoryStd( const T_PostMod& post_mod = T_PostMod(), const T_Allocator& alloc = T_Allocator() );
/** @name Overriden from AbstractFactory */
//@{
/** \brief . */
obj_ptr_t create() const;
//@}
private:
T_PostMod post_mod_;
T_Allocator alloc_;
};
/** \brief Nonmember constructor for an standar abstract factory object.
*
* \relates AbstractFactoryStd
*/
template
RCP >
abstractFactoryStd()
{
return rcp(
new AbstractFactoryStd,AllocatorNew >()
);
}
/** \brief Nonmember constructor for an standar abstract factory object.
*
* \relates AbstractFactoryStd
*/
template
RCP >
abstractFactoryStd( const T_Allocator& alloc = T_Allocator() )
{
return rcp(
new AbstractFactoryStd,T_Allocator>(
PostModNothing(), alloc
)
);
}
// ///////////////////////////////////////////////////////
// Template member definitions
template
inline
AbstractFactoryStd::AbstractFactoryStd(
const T_PostMod& post_mod, const T_Allocator& alloc
)
:post_mod_(post_mod)
,alloc_(alloc)
{}
template
inline
typename AbstractFactoryStd::obj_ptr_t
AbstractFactoryStd::create() const
{
typename T_Allocator::ptr_t
ptr = alloc_.allocate();
post_mod_.initialize(ptr.get());
return ptr;
}
} // end Teuchos
#endif // TEUCHOS_ABSTRACT_FACTORY_STD_HPP