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
99 lines
4 KiB
C++
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*/
|