Diff-Framework: fill in the access variations

no metaprogramming since almost a year ... kindof missed that queer feeling
This commit is contained in:
Fischlurch 2021-01-22 15:06:43 +01:00
parent 05b5ee9a7e
commit c52576ffc7
2 changed files with 74 additions and 85 deletions

View file

@ -60,6 +60,7 @@
#include "lib/diff/gen-node.hpp"
#include "lib/diff/tree-mutator.hpp"
#include "lib/diff/tree-mutator-collection-binding.hpp"
#include "lib/diff/diff-mutable.hpp"
namespace lib {
namespace diff{
@ -71,86 +72,51 @@ namespace diff{
using lib::meta::enable_if;
using lib::meta::Yes_t;
using lib::meta::No_t;
using std::__and_;
using std::__or_;
META_DETECT_FUNCTION(typename X::iterator, begin,(void));
META_DETECT_FUNCTION(GenNode::ID const&, getID,(void));
template<typename T>
class can_recursively_bind_DiffMutable
{
// typedef typename Strip<T>::Type Type;
public:
enum { value = false
// is_iterable::value
// or is_const_iterable::value
// or is_noexcept_iterable::value
// or is_const_noexcept_iterable::value
};
};
template<typename T>
class Is_DiffMutable
struct Can_access_ID
: HasFunSig_getID<typename meta::Strip<T>::Type>
{ };
template<typename T>
class Is_wrapped_DiffMutable
struct Is_DiffMutable
: meta::is_Subclass<T,DiffMutable>
{ };
template<typename T>
class Can_access_ID
struct Is_wrapped_DiffMutable
: __and_< meta::Unwrap<T>
, Is_DiffMutable<typename meta::Unwrap<T>::Type>>
{ };
template<typename T>
struct can_recursively_bind_DiffMutable
: __or_< Is_DiffMutable<T>
, Is_wrapped_DiffMutable<T>>
{ } ;
template<class TAR, typename SEL =void>
struct _AccessID
{
GenNode::ID const&
getID (TAR const& target)
static GenNode::ID const&
getID (TAR const&)
{
throw error::Logic ("Unable to access the target element's object ID. "
"Please define a »Matcher« explicitly by invoking the builder function \"matchElement\".");
}
};
template<class TAR>
struct _AccessID<TAR, enable_if<Can_access_ID<TAR>>>
{
GenNode::ID const&
getID (TAR const& target)
{
return target.getID();
}
};
template<class ELM, typename SEL =void>
struct _AccessTarget
{
DiffMutable&
access (ELM const& elm)
{
throw error::Logic ("Unable to determine if the target is DiffMutable, and how to access it. "
"Please define a »Mutator« explicitly by invoking the builder function \"buildChildMutator\".");
}
};
template<class ELM>
struct _AccessTarget<ELM, enable_if<Is_DiffMutable<ELM>>>
struct _AccessID<ELM, enable_if<Can_access_ID<ELM>>>
{
DiffMutable&
access (ELM const& elm)
static GenNode::ID const&
getID (ELM const& target)
{
return elm;
}
};
template<class ELM>
struct _AccessTarget<ELM, enable_if<Is_wrapped_DiffMutable<ELM>>>
{
DiffMutable&
access (ELM const& elm)
{
return *elm;
return meta::unwrap(target).getID();
}
};
@ -159,8 +125,6 @@ namespace diff{
/** */
template<class ELM>
struct _DefaultBinding<ELM, enable_if<can_recursively_bind_DiffMutable<ELM>>>
: private _AccessTarget<ELM>
, private _AccessID<ELM>
{
template<class COLL>
static auto
@ -169,11 +133,12 @@ namespace diff{
return _EmptyBinding<ELM>::attachTo(coll)
.matchElement([](GenNode const& spec, ELM const& elm)
{
return spec.idi == getID (access (elm));
return spec.idi == _AccessID<ELM>::getID(elm);
})
.buildChildMutator ([&](ELM& target, GenNode::ID const&, TreeMutator::Handle buff) -> bool
{
access(target).buildMutator (buff);
DiffMutable& child = meta::unwrap(target);
child.buildMutator (buff);
return true;
});
}

View file

@ -24,7 +24,8 @@
/** @file trait.hpp
** Helpers for type detection, type rewriting and metaprogramming.
** This header is a collection of frequently used templates for working with types.
** It incurs only modest header inclusion overhead (be sure not to jeopardise that!).
** It incurs only modest header inclusion overhead
** @warning be sure not to jeopardise that!
**
** \par unwrapping
** Strip away all kinds of type adornments, like const, reference, pointer, smart-ptr.
@ -66,11 +67,12 @@
//Forward declarations for the Unwrap helper....
namespace boost{
template<class X> class reference_wrapper;
template<class X> class reference_wrapper;
}
namespace std {
template<class X> class reference_wrapper;
template<class X> class shared_ptr;
template<class X> class shared_ptr;
template<class X, class D> class unique_ptr;
}
namespace lib{
template<class X, class B> class P;
@ -109,17 +111,19 @@ namespace meta {
using std::__or_;
/**
/**
* Helper for type analysis and convenience accessors:
* attempts to extract a base type from various wrappers.
* Additionally allows to extract/deref the wrapped element.
* @note can also be used as a meta function to detect "anything wrapped"
* @warning strips away any const
* @warning also strips away smart-ptrs and lifecycle managers!
*/
template<typename X>
struct Unwrap
: std::false_type
{
typedef X Type;
using Type = X;
static X&
extract (X const& x)
@ -130,14 +134,16 @@ namespace meta {
template<>
struct Unwrap<void> ///< @note we can't unwrap void!
: std::false_type
{
typedef void Type;
using Type = void;
};
template<typename X>
struct Unwrap<X*>
: std::true_type
{
typedef typename std::remove_cv<X>::type Type;
using Type = typename std::remove_cv<X>::type;
static Type&
extract (const X* ptr)
@ -149,8 +155,9 @@ namespace meta {
template<typename X>
struct Unwrap<boost::reference_wrapper<X>>
: std::true_type
{
typedef X Type;
using Type = X;
static X&
extract (boost::reference_wrapper<X> wrapped)
@ -161,8 +168,9 @@ namespace meta {
template<typename X>
struct Unwrap<std::reference_wrapper<X>>
: std::true_type
{
typedef X Type;
using Type = X;
static X&
extract (std::reference_wrapper<X> wrapped)
@ -171,13 +179,28 @@ namespace meta {
}
};
template<typename X>
struct Unwrap<std::shared_ptr<X>>
template<typename X, class D>
struct Unwrap<std::unique_ptr<X,D>>
: std::true_type
{
typedef X Type;
using Type = X;
static X&
extract (std::shared_ptr<X> ptr)
extract (std::unique_ptr<X,D> const& ptr)
{
ASSERT (ptr);
return *ptr;
}
};
template<typename X>
struct Unwrap<std::shared_ptr<X>>
: std::true_type
{
using Type = X;
static X&
extract (std::shared_ptr<X> const& ptr)
{
ASSERT (ptr);
return *ptr;
@ -186,8 +209,9 @@ namespace meta {
template<typename X, class B>
struct Unwrap<P<X, B>>
: std::true_type
{
typedef X Type;
using Type = X;
static X&
extract (P<X,B> ptr)
@ -219,12 +243,12 @@ namespace meta {
template<typename X>
struct Strip
{
typedef typename std::remove_cv<X> ::type TypeUnconst;
typedef typename std::remove_reference<TypeUnconst>::type TypeReferred;
typedef typename std::remove_pointer<TypeReferred> ::type TypePointee;
typedef typename std::remove_cv<TypePointee> ::type TypePlain;
using TypeUnconst = typename std::remove_cv<X> ::type;
using TypeReferred = typename std::remove_reference<TypeUnconst>::type;
using TypePointee = typename std::remove_pointer<TypeReferred> ::type;
using TypePlain = typename std::remove_cv<TypePointee> ::type;
typedef typename Unwrap<TypePlain> ::Type Type;
using Type = typename Unwrap<TypePlain>::Type;
};
@ -373,8 +397,8 @@ namespace meta {
* is not clear we'll trigger those cases, and, when we do, we'll get narrowing
* conversions in a context where we're unable to cope with them or protect
* ourselves against spurious conversions.
* What follows is a quick-n-dirty hack to remove such unwanted conversions.
*
* What follows is a quick-n-dirty hack to remove such unwanted conversions.
*
* [Bug-63723]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63723
*/
template<typename SRC, typename TAR>
@ -436,7 +460,7 @@ namespace meta {
/** Trait template to detect a type usable immediately as
* "Lumiera Forward Iterator" in a specialised for-each loop
* This is just a heuristic, based on some common properties
* of such iterators; it is enough to distinguish it from an
* of such iterators; it is enough to distinguish it from an
* STL container, but can certainly be refined.
*/
template<typename T>
@ -465,7 +489,7 @@ namespace meta {
class can_STL_ForEach
{
typedef typename Strip<T>::Type Type;
struct is_iterable
{
META_DETECT_NESTED(iterator);
@ -477,7 +501,7 @@ namespace meta {
&& HasFunSig_end<Type>::value
};
};
struct is_noexcept_iterable
{
META_DETECT_NESTED(iterator);