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