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:
Fischlurch 2016-01-24 00:00:27 +01:00
parent 02b84cd6dc
commit f4bcdcf4e8
2 changed files with 126 additions and 12 deletions

View file

@ -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";

View file

@ -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&#xe4;hrliche ausschlie&#xdf;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&#xe4;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&#246;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&#228;chlich m&#246;glichen Umwandlungen dr&#252;ber
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="info"/>
</node>
<node CREATED="1453590667630" ID="ID_792450888" MODIFIED="1453590699782" TEXT="&#xfc;berpr&#xfc;ft: mit -O3 und strip bleibt erstaunlich wenig &#xfc;brig"/>
<node CREATED="1453590741428" ID="ID_1733557933" MODIFIED="1453590749327" TEXT="1.6MiB -&gt; 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>