/* GENERATOR.hpp - metaprogramming utilities for generating classes and interfaces Copyright (C) Lumiera.org 2008, Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ==================================================================== This code is heavily inspired by The Loki Library (loki-lib/trunk/include/loki/Sequence.h) Copyright (c) 2001 by Andrei Alexandrescu Copyright (c) 2005 by Peter Kümmel This Loki code accompanies the book: Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design Patterns Applied". Copyright (c) 2001. Addison-Wesley. ISBN 0201704315 Loki Copyright Notice: Permission to use, copy, modify, distribute and sell this software for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The author makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. */ /** @file generator.hpp ** Helpers for working with lib::meta::Types (i.e. lists-of-types). ** The main purpose is to build interfaces and polymorphic implementations ** (using virtual functions) based on templated Types or Collections of types, ** which is not possible without Template Metaprogramming. ** ** The facilities in this header work by instantiating another template, ** which is passed in as (template template) parameter, for each of a ** given sequence of types. What varies is the way how this "for each" ** instantiation is mixed or inherited into the resulting product. ** ** @see generator-test.cpp ** @see lumiera::query::ConfigRules usage example ** @see typelist.hpp ** */ #ifndef LIB_META_GENERATOR_H #define LIB_META_GENERATOR_H #include "lib/meta/typelist.hpp" namespace lib { namespace meta{ /** * Apply a template to a collection of types. * The resulting class ends up inheriting from an instantiation * of the template for each of the types in the list. The inheritance * graph is built in a "mixin" (multiple inheritance) style. */ template < class TYPES // List of Types , template class _X_ // your-template-goes-here , class BASE = NullType // Base class at end of chain > class InstantiateForEach; template class _X_, class BASE> class InstantiateForEach : public BASE { public: typedef BASE Unit; typedef NullType Next; }; template < class TY, typename TYPES , template class _X_ , class BASE > class InstantiateForEach, _X_, BASE> : public _X_, public InstantiateForEach { public: typedef _X_ Unit; typedef InstantiateForEach Next; }; /** Helper to just inherit from the given type(s) */ template struct InheritFrom : T { }; /** * Build a single inheritance chain of template instantiations. * Needs the help of the user provided Template, which now has * to take a second parameter and use this as Base class. * The resulting class ends up (single) inheriting from an * instantiation of the template for each of the types, while * overriding/implementing the provided base class. */ template < class TYPES // List of Types , template class _X_ // your-template-goes-here , class BASE = NullType // Base class at end of chain > class InstantiateChained; template class _X_, class BASE> class InstantiateChained : public BASE { public: typedef BASE Unit; typedef NullType Next; }; template < class TY, typename TYPES , template class _X_ , class BASE > class InstantiateChained, _X_, BASE> : public _X_< TY , InstantiateChained > { public: typedef InstantiateChained Next; typedef _X_ Unit; }; /** * A Variation of InstantiateChained providing an incremented * Index value template parameter. This index can e.g. be used * to store pointers in a dispatcher table in the Base class. * Similar to InstantiateChained, this template builds a linear * chain of inheritance. The user-provided template, which is * to be instantiated for all types in the Typelist, now has to * accept an additional third parameter (uint i). */ template < class TYPES // List of Types , template class _X_ // your-template-goes-here , class BASE = NullType // Base class at end of chain , uint i = 0 // incremented on each instantiation > class InstantiateWithIndex; template< template class _X_ , class BASE , uint i > class InstantiateWithIndex : public BASE { public: typedef BASE Unit; typedef NullType Next; enum{ COUNT = i }; }; template < class TY, typename TYPES , template class _X_ , class BASE , uint i > class InstantiateWithIndex, _X_, BASE, i> : public _X_< TY , InstantiateWithIndex , i > { public: typedef InstantiateWithIndex Next; typedef _X_ Unit; enum{ COUNT = Next::COUNT }; }; }} // namespace lib::meta #endif