LUMIERA.clone/src/lib/builder-qualifier-support.hpp
Ichthyostega ed7e3b4b32 ElementBox: extract builder qualifier support as library implementation
Complete the investigation and turn the solution into a generic
mix-in-template, which can be used in flexible ways to support
this qualifier notation.

Moreover, recapitulate requirements for the ElementBoxWidget
2022-08-28 23:36:27 +02:00

99 lines
4 KiB
C++

/*
BUILDER-QUALIFIER-SUPPORT.hpp - accept arbitrary qualifier terms for builder functions
Copyright (C) Lumiera.org
2022, Hermann Vosseler <Ichthyostega@web.de>
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 <functional>
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 TAR>
class BuilderQualifierSupport
{
protected:
using Manipulator = std::function<void(TAR&)>;
struct Qualifier
: Manipulator
{
using Manipulator::Manipulator;
};
/** Main entrance point: apply the given qualifiers in sequence to the `target`. */
template<class... QUALS>
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*/