/* VARIADIC-HELPER.hpp - metaprogramming utilities for parameter- and type sequences Copyright (C) Lumiera.org 2016, 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 variadic-helper.hpp ** Metaprogramming with type sequences based on variadic template parameters. ** The type rebinding- and helper templates in this header allow to perform ** simple sequence manipulations on sequences of template parameters extracted ** from variadic parameter packs. The goal is to (pre)process flexible argument ** lists _at compile time,_ driven by template instantiation, allowing to specialise ** and react specifically on some concrete pattern of argument types. ** ** @warning the metaprogramming part of Lumiera to deal with type sequences is in a ** state of transition, since C++11 now offers direct language support for ** processing of flexible template parameter sequences ("parameter packs"). ** It is planned to regroup and simplify our homemade type sequence framework ** to rely on variadic templates and integrate better with std::tuple. ** It is clear that we will _retain some parts_ of our own framework, ** since programming with _Loki-style typelists_ is way more obvious ** and straight forward than handling of template parameter packs, ** since the latter can only be rebound through pattern matching. ** @todo transition lib::meta::Types to variadic parameters /////////////////////////////////TICKET #987 ** ** @see control::CommandDef usage example ** @see TupleHelper_test ** @see typelist.hpp ** @see function.hpp ** @see generator.hpp ** */ #ifndef LIB_META_VARIADIC_HELPER_H #define LIB_META_VARIADIC_HELPER_H #include "lib/meta/typelist.hpp" #include "lib/meta/typelist-util.hpp" #include "lib/meta/typeseq-util.hpp" #include "lib/meta/util.hpp" namespace lib { namespace meta { /** * temporary workaround: * alternative definition of "type sequence", * already using variadic template parameters. * @remarks the problem with our existing type sequence type * is that it fills the end of each sequence with NullType, * which was the only way to get a flexible type sequence * prior to C++11. Unfortunately these trailing NullType * entries do not play well with other variadic defs. * @deprecated when we switch our primary type sequence type * to variadic parameters, this type will be obsoleted. */ template struct TySeq { using Seq = TySeq; using List = typename Types::List; }; /** * temporary workaround: additional specialisation for the template * `Prepend` to work also with the (alternative) variadic TySeq. * @see typeseq-util.hpp */ template struct Prepend> { using Seq = TySeq; using List = typename Types::List; }; /** * temporary workaround: strip trailing NullType entries from a * type sequence, to make it compatible with new-style variadic * template definitions. * @note the result type is a TySec, to keep it apart from our * legacy (non-variadic) lib::meta::Types * @deprecated necessary for the transition to variadic sequences */ template struct StripNullType; template struct StripNullType> { using TailSeq = typename StripNullType>::Seq; using Seq = typename Prepend::Seq; }; template struct StripNullType> { using Seq = TySeq<>; // NOTE: this causes the result to be a TySeq }; /** Hold a sequence of index numbers as template parameters */ template struct IndexSeq { template using AppendElm = IndexSeq; }; /** build an `IndexSeq<0, 1, 2, ..., n-1>` */ template struct BuildIndexSeq { using Ascending = typename BuildIndexSeq::Ascending::template AppendElm; template using OffsetBy = typename BuildIndexSeq::template OffsetBy::template AppendElm; template using FilledWith = typename BuildIndexSeq::template FilledWith::template AppendElm; }; template<> struct BuildIndexSeq<0> { using Ascending = IndexSeq<>; template using OffsetBy = IndexSeq<>; template using FilledWith = IndexSeq<>; }; /** build an index number sequence from a structured reference type */ template struct IndexIter; /** build an index number sequence from a type sequence */ template struct IndexIter> { /////TODO as long as Types is not variadic (#987), we need to strip NullType here (instead of just using sizeof...(TYPES) enum {SIZ = lib::meta::count::List>::value }; using Seq = typename BuildIndexSeq::Ascending; }; }} // namespace lib::meta #endif /*LIB_META_VARIADIC_HELPER_H*/