/* CONFIGFLAGS.hpp - Building classes based on configuration cases 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. */ /** @file configflags.hpp ** Under some circumstances it is necessary to assemble functionality ** out of elementary building blocks. Especially, this assembly can be ** expressed as template specialisations directed by a configuration type. ** Thus, the purpose of this header is to encode a flag-like configuraiton ** as distinct types, which can be used to select such specialisations. ** Each possible configuration can be encoded as a list of flags, which allows ** to generate, filter and process those configurations. The final goal is to ** automatically generate a factory which will deliver objects configured ** according to the configuration in question. ** ** @see proc::engine::config::Strategy usage example ** @see proc::engine::config::ConfigSelector ** @see typelist.hpp ** */ #ifndef LUMIERA_META_CONFIGFLAGS_H #define LUMIERA_META_CONFIGFLAGS_H #include "common/meta/typelist.hpp" namespace lumiera { namespace typelist { template struct Flag { typedef Flag ID; }; template<> struct Flag<0> { typedef NullType ID; }; template< char f1=0 , char f2=0 , char f3=0 , char f4=0 , char f5=0 > struct Flags { typedef typename Types< typename Flag::ID , typename Flag::ID , typename Flag::ID , typename Flag::ID , typename Flag::ID >::List Tuple; typedef Tuple List; }; template< char f1=0 , char f2=0 , char f3=0 , char f4=0 , char f5=0 > struct Config ///< distinct type representing a configuration { typedef typename Flags::Tuple Flags; typedef Flags List; }; template struct ConfigSetFlag; ///< set (prepend) the Flag to the given config template< char Fl , char f1 , char f2 , char f3 , char f4 , char IGN > struct ConfigSetFlag > { typedef Config Config; }; /** build a configuration type for the given list-of-flags */ template > struct DefineConfigByFlags { typedef CONF Config; typedef Config Type; }; template struct DefineConfigByFlags< Node,FLAGS>, CONF> { typedef typename ConfigSetFlag< Fl , typename DefineConfigByFlags::Config >::Config Config; typedef Config Type; }; /** * Helper for calculating values and for * invoking runtime code based on a given FlagTuple. * Can also be used on a Typelist of several Configs. * The latter case is typically used to invoke an operation * while ennumerating all Flag-Configurations defined in Code. * An example would be to build (at runtime) an dispatcher table. * Explanation: For the Case covering a List of Configs, we provide * a templated visitaion function, which can accept a functor object * to be invoked on each Configuration. */ template struct FlagInfo; template struct FlagInfo, FLAGS> > { enum{ BITS = MAX(ff, FlagInfo::BITS) , CODE = (1<::CODE }; }; template<> struct FlagInfo { enum{ BITS = 0 , CODE = 0 }; template static typename FUNC::Ret accept (FUNC& functor) { return functor.done(); } }; template struct FlagInfo > { typedef typename CONF::Flags ThisFlags; enum{ BITS = MAX (char(FlagInfo::BITS), char(FlagInfo::BITS)) }; template static typename FUNC::Ret accept (FUNC& functor) { functor.template visit(FlagInfo::CODE); return FlagInfo::accept (functor); } }; } // namespace typelist } // namespace lumiera #endif