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<long> 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.
This commit is contained in:
parent
02b84cd6dc
commit
f4bcdcf4e8
2 changed files with 126 additions and 12 deletions
|
|
@ -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 <boost/noncopyable.hpp>
|
||||
#include <string>
|
||||
|
||||
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<DataValues>::Predicate;
|
||||
|
||||
|
||||
template<typename TAR>
|
||||
class GenNodeAccessor
|
||||
: boost::noncopyable
|
||||
{
|
||||
struct ConverterBase
|
||||
: DataCapPredicate
|
||||
{
|
||||
char buffer[sizeof(TAR)];
|
||||
};
|
||||
|
||||
template<typename TY, class BA>
|
||||
class Converter
|
||||
: public BA
|
||||
{
|
||||
virtual bool
|
||||
handle(TY const& srcElm)
|
||||
{
|
||||
new(&(BA::buffer)) TAR{srcElm};
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
template<typename TY>
|
||||
using can_Convert = std::is_constructible<TAR, TY const&>;
|
||||
|
||||
using PossibleSourceTypes = typename Filter<DataValues::List, can_Convert>::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<TAR>()
|
||||
+"» element from " + string(node));
|
||||
}
|
||||
|
||||
operator TAR ()
|
||||
{
|
||||
return *reinterpret_cast<TAR*> (&converter_.buffer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class, size_t>
|
||||
struct Pick;
|
||||
|
|
@ -99,8 +162,7 @@ struct ElementMapper<Rec, Types<TYPES...>>
|
|||
|
||||
operator TargetType<i> ()
|
||||
{
|
||||
GenNode const& elm = values.child(i);
|
||||
return elm.data.get<TargetType<i>>();
|
||||
return GenNodeAccessor<TargetType<i>>(values.child(i));
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -164,17 +226,17 @@ int
|
|||
main (int, char**)
|
||||
{
|
||||
using NiceTypes = Types<string, int>;
|
||||
using UgglyTypes = Types<Literal, string, short, long, float, TimeVar>;
|
||||
using UgglyTypes = Types<EntryID<long>, string, short, long, float, TimeVar>;
|
||||
|
||||
using Uggs = Tuple<UgglyTypes>;
|
||||
|
||||
// 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 <<endl;
|
||||
cout << urgs <<endl;
|
||||
|
||||
auto uggs = buildTuple<NiceTypes> (args);
|
||||
cout << uggs <<endl;
|
||||
cout << buildTuple<NiceTypes> (args) <<endl;
|
||||
cout << buildTuple<UgglyTypes> (urgs) <<endl;
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -736,15 +736,67 @@
|
|||
</node>
|
||||
<node CREATED="1453546436455" ID="ID_129001401" MODIFIED="1453546551564" TEXT="double-dispatch">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1453546450317" ID="ID_1899026394" MODIFIED="1453546454089" TEXT="Variant-Visitor">
|
||||
<node CREATED="1453546450317" ID="ID_1899026394" MODIFIED="1453590519383" TEXT="Variant-Visitor">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1453546485737" ID="ID_491338311" MODIFIED="1453546493300" TEXT="Gen-Node-Typen"/>
|
||||
<node CREATED="1453546493719" ID="ID_834270776" MODIFIED="1453546496947" TEXT="fest vorgegeben"/>
|
||||
</node>
|
||||
<node CREATED="1453546454484" ID="ID_1643300093" MODIFIED="1453546597358" TEXT="Trampolin">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1453546454484" ID="ID_1643300093" MODIFIED="1453590507167" TEXT="Trampolin">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node CREATED="1453546512277" ID="ID_968193365" MODIFIED="1453590559627" TEXT="Aufruf: generische Iteration">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1453590522161" ID="ID_1369411965" MODIFIED="1453590545513" TEXT="Problem: narrowing conversions">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#990000" CREATED="1453590566651" ID="ID_1367428687" MODIFIED="1453590610375" TEXT="TODO">
|
||||
<icon BUILTIN="flag"/>
|
||||
</node>
|
||||
<node CREATED="1453590585865" ID="ID_350595711" MODIFIED="1453590606670" TEXT="explizit gefährliche ausschließen">
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1453546467707" ID="ID_1543497504" MODIFIED="1453546472446" TEXT="Problem: template bloat">
|
||||
<node CREATED="1453590622236" ID="ID_1084684065" MODIFIED="1453590761460" TEXT="hält sich in Grenzen">
|
||||
<icon BUILTIN="ksmiletris"/>
|
||||
<node CREATED="1453590828976" ID="ID_659078492" MODIFIED="1453590855465" TEXT="eine VTable pro Zieltyp"/>
|
||||
<node CREATED="1453590856220" ID="ID_376478329" MODIFIED="1453590879683">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
eine virtuelle Funktion
|
||||
</p>
|
||||
<p>
|
||||
pro möglichem Umwandlungs-Pfad
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1453590628419" ID="ID_1314031268" MODIFIED="1453590885601">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
wir verwenden die Basis-VTable
|
||||
</p>
|
||||
<p>
|
||||
und layern nur die tatsächlich möglichen Umwandlungen drüber
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1453590667630" ID="ID_792450888" MODIFIED="1453590699782" TEXT="überprüft: mit -O3 und strip bleibt erstaunlich wenig übrig"/>
|
||||
<node CREATED="1453590741428" ID="ID_1733557933" MODIFIED="1453590749327" TEXT="1.6MiB -> 100k"/>
|
||||
</node>
|
||||
<node CREATED="1453546467707" ID="ID_1543497504" MODIFIED="1453546472446" TEXT="Problem: template bloat"/>
|
||||
<node CREATED="1453546512277" ID="ID_968193365" MODIFIED="1453546526943" TEXT="Aufruf: generische Iteration"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue