/* 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 lumiera::typelist::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 Metaprogrmming. ** ** @see lumiera::query::ConfigRules usage example ** @see typelist.hpp ** */ #ifndef LUMIERA_META_GENERATOR_H #define LUMIERA_META_GENERATOR_H #include "lib/meta/typelist.hpp" namespace lumiera { namespace typelist { /** * 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 iheritance * 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; }; /** * 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 templace for each of the types, while * overrideing/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 instantiaton > 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 typelist } // namespace lumiera #endif