/* BUILDER-QUALIFIER-SUPPORT.hpp - accept arbitrary qualifier terms for builder functions Copyright (C) Lumiera.org 2022, 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 builder-qualifier-support.hpp ** Mix-in to support builder functions to accept optional qualifier terms. ** For the classical _builder pattern_ we define a dedicated *builder* class, ** which in turn offers explicitly named setter or configuration functions. ** However, sometimes it is desirable just to offer some builder-like extension ** on regular constructor syntax, where optional additional parameters may be passed ** to adapt the basic setup. Unfortunately, a list of optional further argument tends ** to become hard to read, especially when some dummy arguments must be passed in order ** to supply a setting further down the list. ** ** This mix-in template instead allows to define _qualifier terms,_ and to pass an arbitrary ** sequence of such terms to a constructor or builder function. These qualifiers look like ** "algebraic data types" at invocation site, i.e. they are named terms, optionally even accepting ** further arguments. Yet for the implementation, these qualifiers return a wrapped functor. When ** defined as _friend function,_ the generated qualifier functors may even manipulate private internals ** of the "Builder" or "Strategy" class. ** @warning since these qualifiers manipulate by side-effect, it is up to the user to ensure ** consistent settings and behaviour (typically within a terminal `build()` function). ** @note the `qualify()` function accepts the qualifier functors by-reference; thus it is up ** to the user to either pass them by-value, by reverence or even by perfect forwarding. ** ** @see BuilderQualifierSupport_test ** @see ElementBoxWidget as usage example */ #ifndef LIB_BUILDER_QUALIFIER_SUPPORT_H #define LIB_BUILDER_QUALIFIER_SUPPORT_H #include namespace lib { /** * Mix-in to accept and apply an arbitrary sequence of qualifier functors. * Typically these are used for Builder or Strategy definitions and applied * to some target object, which thereby is manipulated by the qualifiers by * side-effect. * @tparam TAR target type to apply the qualifier functors * @remark the intended usage is to mix-in this template privately and then * to define _qualifier friend functions,_ each binding a suitable lambda * to manipulate the internal settings. This way, at usage site, an arbitrary * sequence of clearly labelled "algebraic terms" can be accepted, to tweak * and adapt the basic features established on the Builder or Strategy. */ template class BuilderQualifierSupport { protected: using Manipulator = std::function; struct Qualifier : Manipulator { using Manipulator::Manipulator; }; /** Main entrance point: apply the given qualifiers in sequence to the `target`. */ template friend void qualify(TAR& target, Qualifier& qualifier, QUALS& ...qs) { qualifier(target); qualify(target, qs...); } friend void qualify(TAR&){ } public: // default construct and copyable }; }// namespace lib #endif /*LIB_BUILDER_QUALIFIER_SUPPORT_H*/