diff --git a/src/lib/format-string.cpp b/src/lib/format-string.cpp index 7931833ab..cf86e2595 100644 --- a/src/lib/format-string.cpp +++ b/src/lib/format-string.cpp @@ -1,5 +1,5 @@ /* - FormatString - string template formatting based on boost::format + FormatString - string template formatting based on boost::format Copyright (C) Lumiera.org 2011, Hermann Vosseler @@ -76,7 +76,7 @@ namespace util { inline void destroyImpl (char* buffer) { - accessImpl(buffer).~format(); + accessImpl(buffer).~format(); } @@ -101,7 +101,7 @@ namespace util { suppressInsufficientArgumentErrors (char* formatter) { using namespace boost::io; - accessImpl(formatter).exceptions (all_error_bits ^ too_few_args_bit); + accessImpl(formatter).exceptions (all_error_bits ^ too_few_args_bit); } diff --git a/src/lib/format-string.hpp b/src/lib/format-string.hpp index 6c3ba455b..bb5384d89 100644 --- a/src/lib/format-string.hpp +++ b/src/lib/format-string.hpp @@ -129,8 +129,8 @@ namespace std { // forward declaration to avoid including namespace lib { - class Literal; - class Symbol; + class Literal; + class Symbol; } @@ -144,7 +144,7 @@ namespace util { - /** + /** * A front-end for using printf-style formatting. * Values to be formatted can be supplied through the * operator%. Custom defined string conversions on objects @@ -180,7 +180,7 @@ namespace util { ~_Fmt (); _Fmt (string formatString); - operator string() const; ///< get the formatted result + operator string() const; ///< get the formatted result template _Fmt& @@ -209,8 +209,8 @@ namespace util { /* ===== forwarding into the implementation ====== */ /** The percent operator (\c '%' ) is used do feed parameter values - * to be included into the formatted result, at the positions marked - * by printf-style placeholders within the format string. + * to be included into the formatted result, at the positions marked + * by printf-style placeholders within the format string. * * \par type specific treatment * Basic types (numbers, chars, strings) are passed to the implementation @@ -236,49 +236,47 @@ namespace util { namespace { // helpers to pick a suitable specialisation.... - /** - * by default we don't allow to + using std::__and_; + using std::__not_; + + /** + * by default we don't allow to * treat any types directly by boost::format. * As fallback we rather just produce a type-ID */ template - struct _allow_call { enum{ value = false };}; + struct _allow_call : std::false_type {}; /* the following definitions enable some primitive types * to be handed over to the boost::format implementation */ - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call{ enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call{ enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call{ enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call: std::true_type { }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call: std::true_type { }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call: std::true_type { }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call : std::true_type { }; #ifndef __x86_64__ - template<> struct _allow_call { enum{ value = true }; }; - template<> struct _allow_call { enum{ value = true }; }; + template<> struct _allow_call : std::true_type { }; + template<> struct _allow_call : std::true_type { }; #endif template struct _shall_format_directly - { - typedef typename lib::meta::UnConst::Type BaseType; - - enum{ value = _allow_call::value }; - }; - - + : _allow_call> + { }; template struct _shall_convert_toString - { - enum{ value = not _shall_format_directly::value - and lib::meta::can_convertToString::value - }; - }; + : __and_<__not_<_shall_format_directly> + , std::bool_constant::value> + > + { }; + template struct _is_smart_wrapper @@ -297,12 +295,10 @@ namespace util { template struct _shall_show_smartWrapper - { - enum{ value = not _shall_convert_toString::value - and _is_smart_wrapper::type>::type>::value - }; - }; + : __and_<__not_<_shall_convert_toString> + ,_is_smart_wrapper>> + > + { }; @@ -426,7 +422,7 @@ namespace util { static void dump (VAL const& val, Implementation& impl) try { - format (string(val), impl); + format (string(val), impl); } catch(std::exception const& ex) { diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 0233249bf..1ff10179d 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -342,11 +342,18 @@ namespace lib { using meta::_Fun; using std::__and_; using std::__not_; + using std::is_const_v; using std::is_base_of; + using std::common_type; + using std::common_type_t; + using std::conditional_t; using std::is_convertible; using std::remove_reference_t; using meta::can_IterForEach; using meta::can_STL_ForEach; + using meta::ValueTypeBinding; + using meta::has_TypeResult; + META_DETECT_FUNCTION_ARGLESS(checkPoint); META_DETECT_FUNCTION_ARGLESS(iterNext); @@ -441,6 +448,38 @@ namespace lib { : _DecoratorTraits { }; + + + /** + * helper to derive a suitable common type when expanding children + * @tparam SRC source iterator fed into the Expander + * @tparam RES result type of the expansion function + */ + template + struct _ExpanderTraits + { + using ResIter = typename _DecoratorTraits::SrcIter; + using SrcYield = typename ValueTypeBinding::value_type; + using ResYield = typename ValueTypeBinding::value_type; + static constexpr bool can_reconcile = + has_TypeResult>(); + + static_assert (can_reconcile, + "source iterator and result from the expansion must yield compatible values"); + static_assert (is_const_v == is_const_v, + "source and expanded types differ in const-ness"); + + // NOTE: unfortunately std::common_type decays (strips cv and reference) + // in C++20, there would be std::common_reference; for now we have to work around that + using CommonType = conditional_t or is_const_v + , const common_type_t + , common_type_t + >; + using value_type = typename ValueTypeBinding::value_type; + using reference = typename ValueTypeBinding::reference; + using pointer = typename ValueTypeBinding::pointer; + }; + }//(End) TreeExplorer traits @@ -628,10 +667,8 @@ namespace lib { { static_assert(can_IterForEach::value, "Lumiera Iterator required as source"); - using ResIter = typename _DecoratorTraits::SrcIter; - static_assert (std::is_convertible(), - "the iterator from the expansion must yield compatible values"); - + using _Trait = _ExpanderTraits; + using ResIter = typename _Trait::ResIter; using RootExpandFunctor = function; using ChldExpandFunctor = function; @@ -694,6 +731,12 @@ namespace lib { public: /* === Iteration control API for IterableDecorator === */ + /** @note result type bindings based on a common type of source and expanded result */ + using value_type = typename _Trait::value_type; + using reference = typename _Trait::reference; + using pointer = typename _Trait::pointer; + + bool checkPoint() const { @@ -703,7 +746,7 @@ namespace lib { or SRC::isValid(); } - typename SRC::reference + reference yield() const { return hasChildren()? **expansions_ diff --git a/src/lib/itertools.hpp b/src/lib/itertools.hpp index 253331bbe..bb5bd899b 100644 --- a/src/lib/itertools.hpp +++ b/src/lib/itertools.hpp @@ -666,12 +666,6 @@ namespace lib { return SingleValIter{forward(something)}; } - template - inline auto - singleValIterator (VAL const& ref) - { - return SingleValIter{ref}; - } /** not-anything-at-all iterator */ template diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index cefed5668..cde6023d7 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -322,6 +322,14 @@ namespace meta { > { }; + /** verify the first (special) type can stand-in for the second */ + template + struct can_StandIn + : std::is_convertible::Reference + ,typename RefTraits::Reference + > + { }; + /** detect various flavours of string / text data */ template struct is_StringLike diff --git a/src/lib/meta/util.hpp b/src/lib/meta/util.hpp index c64a0e714..ce327b281 100644 --- a/src/lib/meta/util.hpp +++ b/src/lib/meta/util.hpp @@ -106,6 +106,35 @@ namespace meta { + namespace { + /** + * @internal helper to detect a nested field `TY::type` or `TY::Type. + * @remark need to use this indirect detection method, since some of the + * type traits from the standard library (notably `std::common_type`) + * use a multiple layer deep indirect definition, which fails to be selected + * on a simple direct template specialisation. + */ + template + class _DetectNested_TypeResult + { + template + static Yes_t check(typename ZZ::type *); + template + static Yes_t check(typename X::Type *); + template + static No_t check(...); + + public: + static const bool value = (sizeof(Yes_t)==sizeof(check(0))); + }; + + } + /** helper to check if another metafunction produced a result type */ + template + struct has_TypeResult : std::bool_constant<_DetectNested_TypeResult::value> { }; + + + /** detect possibility of a conversion to string. * Naive implementation, which first attempts to build a string instance by * implicit conversion, and then tries to invoke an explicit string conversion. @@ -141,35 +170,6 @@ namespace meta { - /** strip const from type: naive implementation */ - template - struct UnConst - { - typedef T Type; - }; - - template - struct UnConst - { - typedef T Type; - }; - template - struct UnConst - { - typedef T* Type; - }; - template - struct UnConst - { - typedef T* Type; - }; - template - struct UnConst - { - typedef T* Type; - }; - - /** Trait template for detecting a typelist type. * For example, this allows to write specialisations diff --git a/src/lib/wrapper.hpp b/src/lib/wrapper.hpp index 8be230728..20e0ef96f 100644 --- a/src/lib/wrapper.hpp +++ b/src/lib/wrapper.hpp @@ -144,7 +144,7 @@ namespace wrapper { class ItemWrapper { - using TY_unconst = typename meta::UnConst::Type ; + using TY_unconst = std::remove_const_t; mutable diff --git a/tests/core/steam/engine/mock-support-test.cpp b/tests/core/steam/engine/mock-support-test.cpp index f93c68931..1e3fa2ead 100644 --- a/tests/core/steam/engine/mock-support-test.cpp +++ b/tests/core/steam/engine/mock-support-test.cpp @@ -34,6 +34,7 @@ #include "lib/util.hpp" #include "lib/format-cout.hpp" #include "lib/test/test-helper.hpp" +#include "lib/meta/duck-detector.hpp"///////////////TODO WIP using test::Test; @@ -43,6 +44,8 @@ namespace lib { namespace iter_explorer { template using DecoTraits = _DecoratorTraits; + template + using ExpoTraits = _ExpanderTraits; }} ///////////////////////////////////////////////////////TODO WIP for investigation namespace steam { @@ -55,6 +58,41 @@ namespace test { using util::isSameObject; using util::seqTuple; +///////////////////////////////////////////////////////TODO WIP for investigation + template + struct ReBind + { + using type = typename U::type; + }; +// template +// struct has_TypeResult : std::false_type { }; +// +// template +// struct has_TypeResult::type> : std::true_type { }; +// +// template +// struct has_TypeResult : std::true_type { }; + +// using lib::meta::Yes_t; +// using lib::meta::No_t; +// +// template +// class HasNested_type +// { +// template +// static Yes_t check(typename X::type *); +// template +// static Yes_t check(typename X::Type *); +// template +// static No_t check(...); +// +// public: +// static const bool value = (sizeof(Yes_t)==sizeof(check(0))); +// }; +// +// template +// struct has_TypeResult : std::bool_constant::value> { }; +///////////////////////////////////////////////////////TODO WIP for investigation /**********************************************************************//** @@ -350,30 +388,31 @@ namespace test { .genNode()}; using RTick = std::reference_wrapper; - auto start = singleValIterator (& util::unConst(mockSegs[Time::ZERO].jobTicket())); + auto start = singleValIterator (mockSegs[Time::ZERO].jobTicket()); - using SrC = lib::iter_explorer::BaseAdapter >; + using SrC = lib::iter_explorer::BaseAdapter >; - auto bunny = [](JobTicket* ticket) + auto bunny = [](JobTicket const& ticket) { - return lib::transformIterator(ticket->getPrerequisites() - ,[](JobTicket const& preq) -> JobTicket* - { return unConst(&preq); } - ); + return ticket.getPrerequisites(); +// return lib::transformIterator(ticket.getPrerequisites() +// ,[](JobTicket const& preq) -> JobTicket* +// { return unConst(&preq); } +// ); }; - using ExIt = decltype(bunny(std::declval())); - // ergibt: lib::TransformIter::IterationState>, const steam::engine::JobTicket&>, steam::engine::JobTicket*> + using ExIt = decltype(bunny(std::declval())); - using Funny = std::function; + using Funny = std::function; Funny funny = bunny; using ExpandedChildren = typename lib::iter_explorer::_FunTraits::Res; using ResIter = typename lib::iter_explorer::DecoTraits::SrcIter; +// lib::test::TypeDebugger buggy; using ResIterVal = typename ResIter::value_type; using SrcIterVal = typename SrC::value_type; - //lib::test::TypeDebugger buggy; +// lib::test::TypeDebugger buggy; // lib::test::TypeDebugger bugggy; using FunResTrait = lib::iter_explorer::_FunTraits; @@ -382,8 +421,38 @@ namespace test { static_assert(std::is_convertible()); // lib::test::TypeDebugger buggy; +// using ResCore = iter_explorer::Expander; using ResCore = lib::iter_explorer::Expander; +// using ExResIter = typename lib::iter_explorer::DecoTraits::SrcIter; +// static_assert(lib::meta::can_IterForEach::value); +// static_assert(lib::meta::can_STL_ForEach::value); + struct Murks + { + using type = void; + }; + struct Gurks : Murks { }; + static_assert(lib::meta::has_TypeResult()); + using Wootz = std::common_type; + using Wauzz = typename Wootz::type; +// lib::test::TypeDebugger bully; + + static_assert(lib::meta::has_TypeResult>()); +// static_assert(HasNested_type::value); +// static_assert(HasNested_type::value); +// static_assert(has_TypeResult()); + + using ExiTrait = lib::iter_explorer::ExpoTraits; + using WrapIter = typename lib::iter_explorer::DecoTraits::SrcIter; +// lib::test::TypeDebugger::reference> bully; +// static_assert(std::is_const_v); +// static_assert(std::is_const_v); +// static_assert(std::is_const_v); +// lib::test::TypeDebugger> bully; +// lib::test::TypeDebugger bully; +// lib::test::TypeDebugger bully; +// lib::test::TypeDebugger bully; + auto it = lib::explore(start) // .transform ([](RTick t) -> JobTicket const& @@ -392,9 +461,9 @@ namespace test { // }) .expand (funny) .expandAll() - .transform ([&](JobTicket * ticket) + .transform ([&](JobTicket const& ticket) { - return ticket->createJobFor(coord).parameter.invoKey.part.a; + return ticket.createJobFor(coord).parameter.invoKey.part.a; }); cout << util::join(it,"-") < @@ -117,19 +118,19 @@ namespace test{ run (Arg) { ExampleStrategy f0; - CHECK ("Strategy{∅}" == string(f0)); + CHECK (f0 == "Strategy{∅}"_expect); ExampleStrategy f1(one()); - CHECK ("Strategy{!one!}" == string(f1)); + CHECK (f1 == "Strategy{!one!}"_expect); ExampleStrategy f2(two("Ψ")); - CHECK ("Strategy{∅.two(Ψ)}" == string(f2)); + CHECK (f2 == "Strategy{∅.two(Ψ)}"_expect); ExampleStrategy f3(one(), two("↯")); - CHECK ("Strategy{!one!.two(↯)}" == string(f3)); + CHECK (f3 == "Strategy{!one!.two(↯)}"_expect); ExampleStrategy f4(two("☭"), one()); - CHECK ("Strategy{!one!}" == string(f4)); // Note: evaluated from left to right, one() overwrites prop_ + CHECK (f4 == "Strategy{!one!}"_expect); // Note: evaluated from left to right, one() overwrites prop_ } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index f83126a5f..5de36ff16 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -70464,6 +70464,11 @@ + + + + + @@ -71257,6 +71262,263 @@ + + + + + + + + + + + + + + + + + + + + +

+ möglicherweise hat damals (2017) das perfect forwarding noch nicht so gut funktioniert (wir verwenden ja debian/stable, das war dann von 2015 und hatte noch etwas ältere Compiler) +

+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ HA!  std::is_convertible<const JobTicket, const JobTicket>()  ⟶ false +

+ +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + +

+ denn es ist letztlich egal, welcher Typ für welchen eintritt +

+ +
+ + + + + + + + + + +

+ nein! das Muster ist nicht symmetrisch +

+ +
+ + + + + + + + + + + + +

+ was bedeutet, das Ergebnis muß ein gemeinsamer Schnitt-Typ von beiden sein +

+ +
+
+ + + + + + +

+ und das bedeutet, daß beide Ergebnistypen einen gemeinsamen Schnitt-Typ haben müssen, der auf den Argumenttyp des Expand-Funktors konvertierbar ist +

+ +
+
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + +

+ ist vielleicht sogar ein Compiler-Bug? +

+
    +
  • + zwar hat std::common_type definitiv eine nested Typedef +
  • +
  • + aber diese wird relativ indirekt erzeugt, über den decltype einer Check-Funktion im Basis-Helper +
  • +
  • + und eine einfache Template-Spezialisierung wird matcht darauf nicht +
  • +
  • + obwohl die gleiche Technik bei einer einfachen Struct funktioniert (selbst bei Vererbung) +
  • +
+ +
+ +
+ + + +
+
+ + + + + + + + + + + + +

+ ...und zwar weil eben auch der IterStack mit involviert ist, und die State-Core-Implementierungs-Funktionen allesamt verzweigen, je nachdem ob schon expandierte Kinder da sind; es bringt nichts, diese Verzweigungs-Struktur irgendwo wegzupacken, entweder man zerreißt sie in zwei Teile (wodurch sie unverständlich wird), oder der Expander selber wird eine leere Hülle, und alle Logik wandert in ein Delegate (wozu das?) +

+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ ...das hat sich nun schon mehrfach als sehr hilfreich erwiesen: man instantiiert das Trait-Template „auf der grünnen Wiese“ und kann es dann direkt mit lib::test::TypeDebugger analysieren... +

+ +
+
+
+ + + + + + +
+
+