From f4bcdcf4e879a29aa3559c78b9608a69b7d5998d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 24 Jan 2016 00:00:27 +0100 Subject: [PATCH] research: full solution, including double-dispatch converter stack now we're able to construct suitable parameter values from the arguments passed embedded in the GenNodes, as is demonstrated with the EntryID constructed from an ID-string. We really need a full-blown double-dispatch, since the content type of the concrete GenNode is only known at runtime (encoded in the RTTI) There is still the problem with generating some spurions additional conversion pathes, some of which are narrowing (and thus dangerous). The copiler emits several warnings here, and all of them are justified. E.g. it would be possible to pass an int64_t in the GenNode and initialise a short from it. This might be convenient at times, but I tend rather to be prohibitive here and thus consider to built in distinct limitations on the allowed conversions. --- research/try.cpp | 76 ++++++++++++++++++++++++++++++++++++---- wiki/thinkPad.ichthyo.mm | 62 +++++++++++++++++++++++++++++--- 2 files changed, 126 insertions(+), 12 deletions(-) diff --git a/research/try.cpp b/research/try.cpp index 64085d3fd..fa95967bb 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -50,26 +50,89 @@ typedef unsigned int uint; #include "lib/symbol.hpp" #include "lib/diff/gen-node.hpp" #include "lib/time/timevalue.hpp" +#include "lib/meta/generator.hpp" +#include "lib/meta/typelist-manip.hpp" #include "lib/meta/tuple-helper.hpp" #include "lib/format-cout.hpp" #include "lib/format-util.hpp" +#include #include using lib::Literal; +using lib::Variant; +using lib::idi::EntryID; using lib::diff::Rec; using lib::diff::MakeRec; using lib::diff::GenNode; +using lib::diff::DataValues; using lib::meta::Types; using lib::meta::Tuple; using lib::meta::IndexSeq; using lib::meta::BuildIndexSeq; +using lib::meta::InstantiateChained; +using lib::meta::Filter; using lib::time::TimeVar; using lib::time::Time; using std::string; using std::tuple; +namespace error = lumiera::error; + + +using DataCapPredicate = Variant::Predicate; + + +template +class GenNodeAccessor + : boost::noncopyable + { + struct ConverterBase + : DataCapPredicate + { + char buffer[sizeof(TAR)]; + }; + + template + class Converter + : public BA + { + virtual bool + handle(TY const& srcElm) + { + new(&(BA::buffer)) TAR{srcElm}; + return true; + }; + }; + + template + using can_Convert = std::is_constructible; + + using PossibleSourceTypes = typename Filter::List; + + using ConversionBuffer = InstantiateChained< PossibleSourceTypes + , Converter + , ConverterBase + >; + + ConversionBuffer converter_; + + public: + GenNodeAccessor (GenNode const& node) + : converter_() + { + if (not node.data.accept (converter_)) + throw error::Invalid ("Unable to build «" + util::typeStr() + +"» element from " + string(node)); + } + + operator TAR () + { + return *reinterpret_cast (&converter_.buffer); + } + }; + template struct Pick; @@ -99,8 +162,7 @@ struct ElementMapper> operator TargetType () { - GenNode const& elm = values.child(i); - return elm.data.get>(); + return GenNodeAccessor>(values.child(i)); } }; @@ -164,17 +226,17 @@ int main (int, char**) { using NiceTypes = Types; - using UgglyTypes = Types; + using UgglyTypes = Types, string, short, long, float, TimeVar>; - using Uggs = Tuple; -// Rec args = MakeRec().scope("lalü", "lala", 12, 34, 5.6, Time(7,8,9)); Rec args = MakeRec().scope("lalü", 42); + Rec urgs = MakeRec().scope("lalü", "lala", 12, 34, 5.6, Time(7,8,9)); cout << args < (args); - cout << uggs < (args) < (urgs) < - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + +

+ eine virtuelle Funktion +

+

+ pro möglichem Umwandlungs-Pfad +

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

+ wir verwenden die Basis-VTable +

+

+ und layern nur die tatsächlich möglichen Umwandlungen drüber +

+ + +
+ +
+ + - -