diff --git a/src/lib/diff/tree-mutator-diffmutable-binding.hpp b/src/lib/diff/tree-mutator-diffmutable-binding.hpp index d790ee253..754888dad 100644 --- a/src/lib/diff/tree-mutator-diffmutable-binding.hpp +++ b/src/lib/diff/tree-mutator-diffmutable-binding.hpp @@ -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 - class can_recursively_bind_DiffMutable - { -// typedef typename Strip::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 - class Is_DiffMutable + struct Can_access_ID + : HasFunSig_getID::Type> { }; template - class Is_wrapped_DiffMutable + struct Is_DiffMutable + : meta::is_Subclass { }; template - class Can_access_ID + struct Is_wrapped_DiffMutable + : __and_< meta::Unwrap + , Is_DiffMutable::Type>> { }; + template + struct can_recursively_bind_DiffMutable + : __or_< Is_DiffMutable + , Is_wrapped_DiffMutable> + { } ; + template 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 - struct _AccessID>> - { - GenNode::ID const& - getID (TAR const& target) - { - return target.getID(); - } - }; - - - template - 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 - struct _AccessTarget>> + struct _AccessID>> { - DiffMutable& - access (ELM const& elm) + static GenNode::ID const& + getID (ELM const& target) { - return elm; - } - }; - template - struct _AccessTarget>> - { - DiffMutable& - access (ELM const& elm) - { - return *elm; + return meta::unwrap(target).getID(); } }; @@ -159,8 +125,6 @@ namespace diff{ /** */ template struct _DefaultBinding>> - : private _AccessTarget - , private _AccessID { template static auto @@ -169,11 +133,12 @@ namespace diff{ return _EmptyBinding::attachTo(coll) .matchElement([](GenNode const& spec, ELM const& elm) { - return spec.idi == getID (access (elm)); + return spec.idi == _AccessID::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; }); } diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index b534d8e5a..95be1bfb1 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -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 reference_wrapper; + template class reference_wrapper; } namespace std { template class reference_wrapper; - template class shared_ptr; + template class shared_ptr; + template class unique_ptr; } namespace lib{ template 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 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 ///< @note we can't unwrap void! + : std::false_type { - typedef void Type; + using Type = void; }; template struct Unwrap + : std::true_type { - typedef typename std::remove_cv::type Type; + using Type = typename std::remove_cv::type; static Type& extract (const X* ptr) @@ -149,8 +155,9 @@ namespace meta { template struct Unwrap> + : std::true_type { - typedef X Type; + using Type = X; static X& extract (boost::reference_wrapper wrapped) @@ -161,8 +168,9 @@ namespace meta { template struct Unwrap> + : std::true_type { - typedef X Type; + using Type = X; static X& extract (std::reference_wrapper wrapped) @@ -171,13 +179,28 @@ namespace meta { } }; - template - struct Unwrap> + template + struct Unwrap> + : std::true_type { - typedef X Type; + using Type = X; static X& - extract (std::shared_ptr ptr) + extract (std::unique_ptr const& ptr) + { + ASSERT (ptr); + return *ptr; + } + }; + + template + struct Unwrap> + : std::true_type + { + using Type = X; + + static X& + extract (std::shared_ptr const& ptr) { ASSERT (ptr); return *ptr; @@ -186,8 +209,9 @@ namespace meta { template struct Unwrap> + : std::true_type { - typedef X Type; + using Type = X; static X& extract (P ptr) @@ -219,12 +243,12 @@ namespace meta { template struct Strip { - typedef typename std::remove_cv ::type TypeUnconst; - typedef typename std::remove_reference::type TypeReferred; - typedef typename std::remove_pointer ::type TypePointee; - typedef typename std::remove_cv ::type TypePlain; + using TypeUnconst = typename std::remove_cv ::type; + using TypeReferred = typename std::remove_reference::type; + using TypePointee = typename std::remove_pointer ::type; + using TypePlain = typename std::remove_cv ::type; - typedef typename Unwrap ::Type Type; + using Type = typename Unwrap::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 @@ -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 @@ -465,7 +489,7 @@ namespace meta { class can_STL_ForEach { typedef typename Strip::Type Type; - + struct is_iterable { META_DETECT_NESTED(iterator); @@ -477,7 +501,7 @@ namespace meta { && HasFunSig_end::value }; }; - + struct is_noexcept_iterable { META_DETECT_NESTED(iterator);