Dispatcher-Pipeline: builder type rebinding problems
...hard to tackle... The idea is to wrap the TreeExplorer builder, so that our specific builder functions can delegated to the (inherited) generic builder functions and would just need to supply some cleverly bound lambdas. However, resulting types are recursive, which does not play nice with type inference, and working around that problem leads to capturing a self reference, which at time of invocation is already invalidated (due to moving the whole pipeline into the final storage)
This commit is contained in:
parent
94fe4a4bec
commit
81ee9a2e67
8 changed files with 369 additions and 64 deletions
|
|
@ -1704,13 +1704,13 @@ namespace lib {
|
|||
/** start building a TreeExplorer
|
||||
* by suitably wrapping the given iterable source.
|
||||
* @return a TreeEplorer, which is an Iterator to yield all the source elements,
|
||||
* but may also be used to build an processing pipeline.
|
||||
* but may also be used to build up a complex processing pipeline.
|
||||
* @warning if you capture the result of this call by an auto variable,
|
||||
* be sure to understand that invoking any further builder operation on
|
||||
* TreeExplorer will invalidate that variable (by moving it into the
|
||||
* augmented iterator returned from such builder call).
|
||||
*
|
||||
* # usage
|
||||
* # Usage
|
||||
*
|
||||
* This function starts a *Builder* expression. It picks up the given source,
|
||||
* which can be something "sequence-like" or "iterable", and will automatically
|
||||
|
|
|
|||
|
|
@ -43,7 +43,9 @@
|
|||
#include "steam/engine/job-ticket.hpp"
|
||||
#include "steam/engine/job-planning.hpp"
|
||||
#include "steam/play/output-slot.hpp"
|
||||
#include "lib/iter-tree-explorer.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/nocopy.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
|
|
@ -82,7 +84,7 @@ namespace engine {
|
|||
* which, for the purpose of dispatching a series of jobs just looks
|
||||
* like a sequence of job descriptors
|
||||
*
|
||||
* @todo 10/12 still WIP, but conceptually settled by now
|
||||
* @todo 6/23 API is remoulded from ground up (»Playback Vertical Slice« integration effort)
|
||||
*/
|
||||
class Dispatcher
|
||||
: public FrameLocator
|
||||
|
|
@ -106,13 +108,28 @@ namespace engine {
|
|||
};
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1301 : obsolete
|
||||
|
||||
using FrameNrIter = lib::NumIter<FrameCnt>;
|
||||
|
||||
struct PipelineBuilder
|
||||
: lib::SingleValIter<TimeVar> ////////////////////////////////////////OOO placeholder type; should rather be a TreeExplorer!
|
||||
: FrameNrIter
|
||||
{
|
||||
PipelineBuilder&
|
||||
Dispatcher* dispatcher;
|
||||
Timings timings;
|
||||
ModelPort port;
|
||||
DataSink sink;
|
||||
|
||||
auto
|
||||
timeRange (Time start, Time after)
|
||||
{
|
||||
UNIMPLEMENTED ("setup dispatch time range");
|
||||
auto frame = [&](Time t){ return timings.getBreakPointAfter(t); };
|
||||
auto reset = [&](auto i){ static_cast<FrameNrIter&>(*this) = i; };
|
||||
|
||||
reset (lib::eachNum (frame(start), frame(after)));
|
||||
return lib::treeExplore (move(*this))
|
||||
.transform ([&](FrameCnt frameNr) -> TimeVar //////////////////////////////TICKET #1261 : transform-iterator unable to handle immutable time
|
||||
{
|
||||
return timings.getFrameStartAt (frameNr);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -126,7 +143,7 @@ namespace engine {
|
|||
|
||||
PipelineBuilder forCalcStream(Timings timings, ModelPort port, DataSink sink)
|
||||
{
|
||||
UNIMPLEMENTED ("create Pipeline builder");
|
||||
return PipelineBuilder{FrameNrIter(), this, timings, port, sink};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,40 +30,33 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
|
||||
//#include "steam/engine/procnode.hpp"
|
||||
#include "steam/play/dummy-play-connection.hpp"
|
||||
#include "steam/mobject/model-port.hpp"
|
||||
#include "steam/engine/dispatcher.hpp"
|
||||
#include "steam/play/timings.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
//#include "lib/time/timequant.hpp"
|
||||
//#include "lib/format-cout.hpp"
|
||||
#include "lib/depend.hpp"
|
||||
#include "lib/itertools.hpp"
|
||||
#include "lib/util-coll.hpp"
|
||||
//#include "lib/util-coll.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
//#include <functional>
|
||||
//#include <vector>
|
||||
|
||||
using test::Test;
|
||||
using util::isnil;
|
||||
using util::last;
|
||||
using std::vector;
|
||||
using std::function;
|
||||
//using std::rand;
|
||||
//using std::vector;
|
||||
//using std::function;
|
||||
using std::rand;
|
||||
|
||||
|
||||
namespace steam {
|
||||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
using lib::time::FSecs;
|
||||
using lib::time::FrameCnt;
|
||||
using lib::time::FrameRate;
|
||||
using lib::time::Duration;
|
||||
using lib::time::Offset;
|
||||
using lib::time::TimeValue;
|
||||
using lib::time::Time;
|
||||
using mobject::ModelPort;
|
||||
using play::Timings;
|
||||
|
||||
namespace { // Test fixture...
|
||||
|
|
@ -75,17 +68,6 @@ namespace test {
|
|||
const uint DUMMY_CHANNEL(0); /////////////////////////////////////////////////////////////TICKET #1297 : get rid of the channels (use different ModelPort)
|
||||
|
||||
|
||||
// ModelPort
|
||||
// getTestPort()
|
||||
// {
|
||||
// using play::test::ModelPorts;
|
||||
// using play::test::PlayTestFrames_Strategy;
|
||||
// using DummyPlaybackSetup = play::test::DummyPlayConnection<PlayTestFrames_Strategy>;
|
||||
//
|
||||
// DummyPlaybackSetup dummySetup;
|
||||
// ModelPorts mockModelPorts = dummySetup.provide_testModelPorts();
|
||||
// return *mockModelPorts; // using just the first dummy port
|
||||
// }
|
||||
|
||||
|
||||
FSecs
|
||||
|
|
|
|||
265
tests/core/steam/play/dummy-builder-context.hpp
Normal file
265
tests/core/steam/play/dummy-builder-context.hpp
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
DUMMY-BUILDER-CONTEXT.hpp - fake simulated builder result for player tests
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2011, Hermann Vosseler <Ichthyostega@web.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/** @file dummy-builder-context.hpp
|
||||
** Simulated result of a builder run for test purposes, without actual session and model content.
|
||||
** Integration tests for the render engine or the player have to deal with a lot of prerequisites,
|
||||
** since both an external environment and actual content form the Session is required to start any
|
||||
** processing. Effectively the complete core application is required — while in fact the engine is
|
||||
** built in an abstracted way and does not need to know much about the rest of the application.
|
||||
** Thus, as a remedy, it is possible to establish a _faked context,_ exposing just those interfaces
|
||||
** used by the engine for processing. As additional benefit, dedicated test operations can be rigged
|
||||
** and verification routines can be used in place of actual media output.
|
||||
**
|
||||
** This faked builder context provides a selection of consistent media element IDs with sensible
|
||||
** properties and type markers, plus the attachment points for a simulated model structure, as
|
||||
** if generated from an actual session model by a real Builder run.
|
||||
** - a set of ModelPort elements
|
||||
** - a set of DataSink handles, as if an actual playback connection has been established
|
||||
** @todo 5/2023 add more elements as needed for test driven integration of Player and engine
|
||||
** @todo this was invented in 2012 -- but development of the player subsystem stalled thereafter.
|
||||
**
|
||||
** @see mock-dispatcher.hpp
|
||||
** @see JobPlanningSetup_test
|
||||
*/
|
||||
|
||||
|
||||
#ifndef STEAM_PLAY_DUMMY_BUILDER_CONTEXT_H
|
||||
#define STEAM_PLAY_DUMMY_BUILDER_CONTEXT_H
|
||||
|
||||
|
||||
#include "steam/mobject/model-port.hpp"
|
||||
#include "steam/mobject/builder/model-port-registry.hpp"
|
||||
#include "steam/play/output-slot-connection.hpp"
|
||||
#include "steam/play/output-manager.hpp"
|
||||
#include "steam/asset/timeline.hpp"
|
||||
#include "steam/asset/pipe.hpp"
|
||||
#include "common/query.hpp"
|
||||
|
||||
#include "lib/iter-source.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace steam{
|
||||
namespace play {
|
||||
namespace test {
|
||||
|
||||
|
||||
/**
|
||||
* @todo 5/2023 quick-n-dirty placeholder to be able to fabricate fake DataSink handles (`Handle<Connection>`)
|
||||
*/
|
||||
class UnimplementedConnection
|
||||
: public play::OutputSlot::Connection
|
||||
{
|
||||
BuffHandle claimBufferFor(FrameID) override { UNIMPLEMENTED ("claimBufferFor(FrameID)"); }
|
||||
bool isTimely (FrameID, TimeValue) override { return true; }
|
||||
void transfer (BuffHandle const&) override { UNIMPLEMENTED ("transfer (BuffHandle const&)"); }
|
||||
void pushout (BuffHandle const&) override { UNIMPLEMENTED ("pushout (BuffHandle const&)"); }
|
||||
void discard (BuffHandle const&) override { UNIMPLEMENTED ("discard (BuffHandle const&)"); }
|
||||
void shutDown () override { UNIMPLEMENTED ("shutDown() Connection"); }
|
||||
|
||||
public:
|
||||
~UnimplementedConnection();
|
||||
UnimplementedConnection() = default;
|
||||
};
|
||||
|
||||
|
||||
using asset::Pipe;
|
||||
using asset::PPipe;
|
||||
using asset::Struct;
|
||||
using asset::Timeline;
|
||||
using asset::PTimeline;
|
||||
using mobject::ModelPort;
|
||||
using mobject::builder::ModelPortRegistry;
|
||||
using util::contains;
|
||||
using lumiera::Query;
|
||||
|
||||
|
||||
using PID = asset::ID<Pipe>;
|
||||
using TID = asset::ID<Struct>;
|
||||
|
||||
using ModelPorts = lib::IterSource<mobject::ModelPort>::iterator;
|
||||
using DummyOutputLink = std::pair<mobject::ModelPort, play::DataSink>;
|
||||
|
||||
|
||||
inline PID
|
||||
getPipe (string id)
|
||||
{
|
||||
return Pipe::query ("id("+id+")");
|
||||
}
|
||||
|
||||
inline TID
|
||||
getTimeline (string id)
|
||||
{
|
||||
return asset::Struct::retrieve (Query<Timeline> ("id("+id+")"))->getID();
|
||||
}
|
||||
|
||||
const uint NUMBER_OF_PORTS = 2;
|
||||
const string namePortA("bus-A");
|
||||
const string namePortB("bus-B");
|
||||
|
||||
/**
|
||||
* helper for dummy render engine:
|
||||
* Simulate the result of a build process,
|
||||
* without actually running the builder.
|
||||
* Produces some mock pipes, model ports etc.
|
||||
*/
|
||||
struct SimulatedBuilderContext
|
||||
{
|
||||
ModelPortRegistry registry_;
|
||||
ModelPortRegistry* existingRegistry_;
|
||||
|
||||
std::vector<ModelPort> modelPorts_;
|
||||
std::vector<DataSink> dataSinks_;
|
||||
|
||||
/** setup */
|
||||
SimulatedBuilderContext()
|
||||
: registry_()
|
||||
, existingRegistry_(ModelPortRegistry::setActiveInstance (registry_))
|
||||
{
|
||||
performMockBuild();
|
||||
}
|
||||
|
||||
/** tear-down */
|
||||
~SimulatedBuilderContext()
|
||||
{
|
||||
if (existingRegistry_)
|
||||
ModelPortRegistry::setActiveInstance (*existingRegistry_);
|
||||
else
|
||||
ModelPortRegistry::shutdown();
|
||||
}
|
||||
|
||||
void
|
||||
performMockBuild()
|
||||
{
|
||||
PID pipeA = getPipe (namePortA);
|
||||
PID pipeB = getPipe (namePortB);
|
||||
TID someTimeline = getTimeline ("dummy_Timeline");
|
||||
|
||||
// start out with defining some new model ports......
|
||||
registry_.definePort (pipeA, someTimeline);
|
||||
registry_.definePort (pipeB, someTimeline);
|
||||
|
||||
registry_.commit();
|
||||
|
||||
// now "bus-A" and "bus-B" are known as model ports
|
||||
modelPorts_.push_back (ModelPort(pipeA));
|
||||
modelPorts_.push_back (ModelPort(pipeB));
|
||||
|
||||
// prepare corresponding placeholder DataSink (a fake active output connection)
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
dataSinks_.emplace_back().activate(std::make_shared<UnimplementedConnection>());
|
||||
}
|
||||
|
||||
|
||||
ModelPorts
|
||||
getAllModelPorts()
|
||||
{
|
||||
return lib::iter_source::eachEntry (modelPorts_.begin(), modelPorts_.end());
|
||||
}
|
||||
|
||||
DummyOutputLink
|
||||
getModelPort (uint index)
|
||||
{
|
||||
REQUIRE (index < modelPorts_.size());
|
||||
return {modelPorts_[index]
|
||||
,dataSinks_[index]
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
/****************************************************************//**
|
||||
* Framework for dummy playback and rendering.
|
||||
* A DummyPlayConnection provides a coherent set of placeholders,
|
||||
* allowing to start a data producing process while leaving out
|
||||
* various parts of the real engine implementation. The specific
|
||||
* mode of operation, suitable for various test scenarios, may be
|
||||
* fine tuned by the strategy object defined as template parameter.
|
||||
*
|
||||
* @todo not-yet-implemented as of 2016 -- but the design can be considered valid.
|
||||
*/
|
||||
template<class DEF>
|
||||
class DummyPlayConnection
|
||||
: util::NonCopyable
|
||||
{
|
||||
SimulatedBuilderContext mockBuilder_;
|
||||
|
||||
public:
|
||||
|
||||
ModelPorts
|
||||
getAllModelPorts()
|
||||
{
|
||||
return mockBuilder_.getAllModelPorts();
|
||||
}
|
||||
|
||||
DummyOutputLink
|
||||
getModelPort (uint index)
|
||||
{
|
||||
return mockBuilder_.getModelPort (index);
|
||||
}
|
||||
|
||||
POutputManager
|
||||
provide_testOutputSlot()
|
||||
{
|
||||
UNIMPLEMENTED ("provide a suitable output sink simulation");
|
||||
}
|
||||
|
||||
|
||||
/* === Test Support API === */
|
||||
|
||||
bool
|
||||
isWired()
|
||||
{
|
||||
UNIMPLEMENTED ("is this dummy in activated state?");
|
||||
}
|
||||
|
||||
Duration
|
||||
getPlannedTestDuration()
|
||||
{
|
||||
UNIMPLEMENTED ("manage the a planned test duration");
|
||||
}
|
||||
|
||||
/** test helper: blocking wait during an output test.
|
||||
* The waiting time should be in accordance with the
|
||||
* \link #getPlannedTestduration planned value \endlink,
|
||||
*/
|
||||
void
|
||||
waitUntilDue()
|
||||
{
|
||||
UNIMPLEMENTED ("do a blocking wait, while an output test is performed in other threads");
|
||||
}
|
||||
|
||||
bool
|
||||
gotCorrectOutput()
|
||||
{
|
||||
UNIMPLEMENTED ("verify proper operation by inspecting the provided test dummy components");
|
||||
}
|
||||
};
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1301
|
||||
|
||||
|
||||
}}} // namespace steam::play::test
|
||||
#endif /*STEAM_PLAY_DUMMY_BUILDER_CONTEXT_H*/
|
||||
|
|
@ -28,8 +28,6 @@
|
|||
#include "lib/test/run.hpp"
|
||||
|
||||
#include "steam/play/dummy-play-connection.hpp"
|
||||
//#include "steam/engine/buffhandle.hpp"
|
||||
//#include "steam/engine/testframe.hpp"
|
||||
#include "include/play-facade.hpp"
|
||||
#include "lib/time/control.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -78,19 +78,9 @@
|
|||
#define STEAM_PLAY_DUMMY_PLAY_CONNECTION_H
|
||||
|
||||
|
||||
//#include "include/dummy-player-facade.h"
|
||||
//#include "include/display-facade.h"
|
||||
//#include "common/instancehandle.hpp"
|
||||
//#include "lib/singleton-ref.hpp"
|
||||
#include "steam/play/output-slot-connection.hpp"
|
||||
#include "steam/play/dummy-builder-context.hpp"
|
||||
#include "steam/play/output-manager.hpp"
|
||||
#include "steam/mobject/model-port.hpp"
|
||||
#include "lib/time/timequant.hpp"
|
||||
//#include "lib/scoped-collection.hpp"
|
||||
#include "steam/mobject/builder/model-port-registry.hpp"
|
||||
#include "steam/asset/timeline.hpp"
|
||||
#include "steam/asset/pipe.hpp"
|
||||
#include "common/query.hpp"
|
||||
|
||||
#include "lib/iter-source.hpp"
|
||||
#include "lib/nocopy.hpp"
|
||||
|
|
@ -104,18 +94,12 @@ namespace play {
|
|||
namespace test {
|
||||
|
||||
// using std::string;
|
||||
// using lumiera::Subsys;
|
||||
// using lumiera::Display;
|
||||
// using lumiera::DummyPlayer;
|
||||
using lib::time::Duration;
|
||||
|
||||
using ModelPorts = lib::IterSource<mobject::ModelPort>::iterator;
|
||||
|
||||
using DummyOutputLink = std::pair<mobject::ModelPort, play::DataSink>;
|
||||
|
||||
/**
|
||||
/*
|
||||
* @todo 5/2023 quick-n-dirty placeholder to be able to fabricate fake DataSink handles (`Handle<Connection>`)
|
||||
*/
|
||||
* /
|
||||
class UnimplementedConnection
|
||||
: public play::OutputSlot::Connection
|
||||
{
|
||||
|
|
@ -130,7 +114,7 @@ namespace test {
|
|||
~UnimplementedConnection();
|
||||
UnimplementedConnection() = default;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
|
@ -139,7 +123,7 @@ namespace test {
|
|||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
namespace { // simulated builder environment
|
||||
|
||||
using asset::Pipe;
|
||||
|
|
@ -176,12 +160,12 @@ namespace test {
|
|||
const string namePortA("bus-A");
|
||||
const string namePortB("bus-B");
|
||||
|
||||
/**
|
||||
/ **
|
||||
* helper for dummy render engine:
|
||||
* Simulate the result of a build process,
|
||||
* without actually running the builder.
|
||||
* Produces some mock pipes, model ports etc.
|
||||
*/
|
||||
* /
|
||||
struct SimulatedBuilderContext
|
||||
{
|
||||
ModelPortRegistry registry_;
|
||||
|
|
@ -190,7 +174,6 @@ namespace test {
|
|||
std::vector<ModelPort> modelPorts_;
|
||||
std::vector<DataSink> dataSinks_;
|
||||
|
||||
/** setup */
|
||||
SimulatedBuilderContext()
|
||||
: registry_()
|
||||
, existingRegistry_(ModelPortRegistry::setActiveInstance (registry_))
|
||||
|
|
@ -198,7 +181,6 @@ namespace test {
|
|||
performMockBuild();
|
||||
}
|
||||
|
||||
/** tear-down */
|
||||
~SimulatedBuilderContext()
|
||||
{
|
||||
if (existingRegistry_)
|
||||
|
|
@ -246,7 +228,7 @@ namespace test {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/****************************************************************//**
|
||||
* Framework for dummy playback and rendering.
|
||||
|
|
@ -73527,12 +73527,73 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685676373201" ID="ID_290916668" MODIFIED="1685676382028" TEXT="soll von TreeExplorer erben">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1685676390323" ID="ID_1302265239" MODIFIED="1685676394025" TEXT="geht das?">
|
||||
<node COLOR="#435e98" CREATED="1685676390323" ID="ID_1302265239" MODIFIED="1685743982852" TEXT="geht das?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1685676395607" ID="ID_840485660" MODIFIED="1685676404942" TEXT="erinnere mich an den EventLog-Filter"/>
|
||||
<node CREATED="1685676405602" ID="ID_1339853853" MODIFIED="1685676416909" TEXT="das läuft auf einen decltype-Trick hinaus">
|
||||
<node CREATED="1685676395607" ID="ID_840485660" MODIFIED="1685743976291" TEXT="erinnere mich an den EventLog-Filter">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
siehe <font face="Monospaced" size="2" color="#4c409c">iter-chain-search.hpp</font>
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node CREATED="1685676405602" ID="ID_1339853853" MODIFIED="1685743938073" TEXT="das läuft auf einen decltype-Trick hinaus">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...man packt den eigentlichen TreeExplorer-Builder-Aufruf in eine Hilfsunktion und greift den decltype vom Rückgabewert ab; von diesem Typ kann man dann erben (und verwendet die erwähnte Hilfsfunktion im Konstruktor, um den Parent-Typ zu initialisieren)i
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685744020440" ID="ID_189611589" MODIFIED="1685744043568" TEXT="das eigene Builder-API soll aber auf TreeExplorer aufbauen können">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685743991581" ID="ID_865546443" MODIFIED="1685744014683" TEXT="Type-Rebinding einrichten">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1685744055315" ID="ID_115548313" MODIFIED="1685754522949" TEXT="für Basis-Konstruktion">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1685754130097" ID="ID_286369938" MODIFIED="1685754149459" TEXT="schwierig">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1685754164717" ID="ID_1228626909" MODIFIED="1685754376312" TEXT="rekursive Struktur ⟺ type inference">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
In diesem Zusammenhang ist <i>type inference </i>praktisch unvermeidbar, denn die komplexen Typen vom TreeExplorer können anders nicht explizit gemacht werden — aber das Problem ist, die Typen sind rekursiv, denn den neuen, erweiterten Builder-Typ muß ich schon kennen, um ihn in dem TreeEplorer-Builder als Core zu übergeben, aber erst <i>durch diesen Aufruf</i> wird dieser neue erweiterte Builder überhaupt definiert
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1685754386041" ID="ID_1627047385" MODIFIED="1685754500941" TEXT="Trick: NumIter ist assignable">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...also zunächst einen deaktivierten NumIter als Basisklasse, und an diesen später einen aktivierten NumIter zuweisen...  <b><font color="#ec1313">ziemlich häßlich</font></b>, aber damit bekomme ich es überhaupt erst mal durch den Compiler...
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1685744060666" ID="ID_676050987" MODIFIED="1685744074319" TEXT="für Anwendung von TreeExplorer-Builder-Funktionen">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue