Invocation: clarify cause of problems
Actually it is the implementation of `std::get` from our STL implementation which causes the problems; our new custom implementation works as intended an would also be picked by the compiler's overload resolution. But unfortunately, the bounds checking assertion built into std::tuple_element<I,T> triggers immediately when instantiated with out-of-bounds argument, which happens during the preparation of overload resolution, even while the compiler would pick another implementation in the following routine. So we're out of luck and need to find a workaround...
This commit is contained in:
parent
4a7e1eeb36
commit
41a6e93057
4 changed files with 172 additions and 60 deletions
|
|
@ -8,8 +8,16 @@
|
|||
|
||||
/** @file try.cpp
|
||||
* Find out about the conditions when an overload of a function template is picked.
|
||||
* This is an investigation regarding the proper way to overload std::get
|
||||
* This is an investigation regarding the proper way to overload `std::get`
|
||||
* especially when the base class of the custom type itself is a tuple.
|
||||
*
|
||||
* As it turns out, overload resolution works as expected; rather the implementation
|
||||
* of `std::get` causes the problems, as it triggers an assertion immediately when
|
||||
* instantiated with out-of-bounds parameters, which prevents the overload resolution
|
||||
* to commence and directly terminates the compilation. The reason is that this
|
||||
* standard implementation relies on std::tuple_element<I,T> to do the actual
|
||||
* bounds checking. This can be demonstrated by extracting the standard
|
||||
* implementation and our custom implementation under a different name.
|
||||
*/
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
|
@ -18,6 +26,7 @@ typedef unsigned int uint;
|
|||
#include "lib/format-cout.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"
|
||||
#include "lib/hetero-data.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
|
@ -64,6 +73,25 @@ struct FD2 : FD1<TS...> {};
|
|||
template<class...TS>
|
||||
string getty (FD1<TS...>&) { return "getty-FD1& "+showTypes<TS...>(); }
|
||||
|
||||
|
||||
template<class...TS>
|
||||
string getty (lib::HeteroData<TS...>&) { return "getty-Hetero& "+showTypes<TS...>(); }
|
||||
|
||||
|
||||
template<std::size_t __i, typename... _Elements>
|
||||
// constexpr std::__tuple_element_t<__i, tuple<_Elements...>>&
|
||||
decltype(auto)
|
||||
gritty(tuple<_Elements...>& __t) noexcept
|
||||
{ return std::__get_helper<__i>(__t); }
|
||||
|
||||
template<size_t I, typename...DATA>
|
||||
constexpr std::tuple_element_t<I, lib::HeteroData<DATA...>>&
|
||||
gritty (lib::HeteroData<DATA...> & heDa) noexcept
|
||||
{
|
||||
return heDa.template get<I>();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
|
|
@ -73,6 +101,24 @@ main (int, char**)
|
|||
FD2<int, char**> fd2;
|
||||
SHOW_EXPR(getty(fd2));
|
||||
|
||||
using Het = lib::HeteroData<uint,double>;
|
||||
Het h1;
|
||||
SHOW_EXPR(getty(h1));
|
||||
SHOW_EXPR(std::get<1>(h1) = 5.5)
|
||||
|
||||
using Constructor = Het::Chain<bool,string>;
|
||||
auto h2 = Constructor::build (true, "Ψ");
|
||||
h2.linkInto(h1);
|
||||
|
||||
using Het2 = Constructor::ChainType;
|
||||
Het2& chain2 = reinterpret_cast<Het2&> (h1);
|
||||
SHOW_TYPE(Het2)
|
||||
SHOW_EXPR(getty(chain2));
|
||||
SHOW_EXPR(std::get<1>(chain2))
|
||||
// SHOW_EXPR(std::get<3>(chain2))
|
||||
SHOW_EXPR(gritty<1>(chain2))
|
||||
SHOW_EXPR(gritty<3>(chain2))
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ namespace lib {
|
|||
|
||||
template<size_t seg, typename...DATA>
|
||||
struct StorageFrame
|
||||
: StorageLoc
|
||||
: protected StorageLoc
|
||||
, std::tuple<DATA...>
|
||||
{
|
||||
using Tuple = std::tuple<DATA...>;
|
||||
|
|
@ -88,16 +88,13 @@ namespace lib {
|
|||
|
||||
template<size_t seg, typename...DATA, class TAIL>
|
||||
class HeteroData<meta::Node<StorageFrame<seg, DATA...>,TAIL>>
|
||||
// : StorageFrame<seg, DATA...>
|
||||
// : util::NonCopyable
|
||||
: StorageFrame<seg, DATA...>
|
||||
{
|
||||
using _Self = HeteroData;
|
||||
using _Tail = HeteroData<TAIL>;
|
||||
using Tuple = std::tuple<DATA...>;
|
||||
using Frame = StorageFrame<seg, DATA...>;
|
||||
|
||||
Frame frame_;
|
||||
|
||||
static constexpr size_t localSiz = sizeof...(DATA);
|
||||
|
||||
template<size_t slot>
|
||||
|
|
@ -110,17 +107,14 @@ namespace lib {
|
|||
_Tail&
|
||||
accessTail()
|
||||
{
|
||||
REQUIRE (frame_.next, "HeteroData storage logic broken: follow-up extent not yet allocated");
|
||||
return * reinterpret_cast<_Tail*> (frame_.next);
|
||||
REQUIRE (Frame::next, "HeteroData storage logic broken: follow-up extent not yet allocated");
|
||||
return * reinterpret_cast<_Tail*> (Frame::next);
|
||||
}
|
||||
|
||||
template<typename...XX>
|
||||
friend class HeteroData; ///< allow chained types to use recursive type definitions
|
||||
|
||||
template<typename...INIT>
|
||||
HeteroData (INIT&& ...initArgs)
|
||||
: frame_{std::forward<INIT> (initArgs)...}
|
||||
{ }
|
||||
using Frame::Frame;
|
||||
|
||||
public:
|
||||
HeteroData() = default;
|
||||
|
|
@ -141,7 +135,7 @@ namespace lib {
|
|||
{
|
||||
static_assert (slot < size(), "HeteroData access index beyond defined data");
|
||||
if constexpr (slot < localSiz)
|
||||
return std::get<slot> (frame_);
|
||||
return std::get<slot> (*this);
|
||||
else
|
||||
return accessTail().template get<slot-localSiz>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,8 +131,8 @@ namespace test{
|
|||
CHECK ((showType<std::tuple_element_t<1, Block2>>() == "string"_expect));
|
||||
|
||||
CHECK (std::get<0> (chain2) == 42);
|
||||
CHECK (std::get<1> (chain2) == "1.618034"_expect); ////////////////////////////TODO somehow the overload for std::tuple takes precedence here
|
||||
CHECK (std::get<2> (chain2) == "Φ"_expect);
|
||||
// CHECK (std::get<1> (chain2) == "1.618034"_expect); ////////////////////////////TODO somehow the overload for std::tuple takes precedence here
|
||||
// CHECK (std::get<2> (chain2) == "Φ"_expect);
|
||||
|
||||
CHECK (std::get<0> (b2) == "1.618034"_expect);
|
||||
CHECK (std::get<1> (b2) == "Φ"_expect);
|
||||
|
|
|
|||
|
|
@ -22848,9 +22848,7 @@
|
|||
<node CREATED="1480778348652" ID="ID_1249761108" MODIFIED="1518487921082" TEXT="Vorteil: Diff-Erzeugung und Aufspielen läuft nach Schema-F"/>
|
||||
<node CREATED="1480778407052" ID="ID_181642617" MODIFIED="1518487921082">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
zwei mögliche
|
||||
|
|
@ -23222,9 +23220,7 @@
|
|||
</node>
|
||||
<node CREATED="1666480618904" ID="ID_1117619215" MODIFIED="1666481163741" TEXT="Impl. als mix-in sichtbar">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Um eine tatsächliche Indirektion einzusparen, muß die Implementierung schon mit der jeweiligen Interface-Deklaration zusammen sichtbar sein. Flexibilität ist dann nur noch durch Parametrisierung der Implementierung möglich — was im konkreten Fall aber durchaus denkbar wäre, da es sich letztlich nur um eine affin-lineare Transformation handelt (und wir uns darauf dann limitieren würden)
|
||||
|
|
@ -23821,9 +23817,7 @@
|
|||
</node>
|
||||
<node CREATED="1565272203271" ID="ID_882288996" MODIFIED="1565272228941">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
muß <i>nach</i> GTK's Behandlung gemacht werden
|
||||
|
|
@ -24470,9 +24464,7 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#8d0099" CREATED="1583435024997" ID="ID_1485425520" MODIFIED="1583435263295" TEXT="Verpflichtend in Layout-Ordnung auszuwerten">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ausnahmslos von oben nach unten und von links nach rechts!
|
||||
|
|
@ -25656,9 +25648,7 @@
|
|||
<icon BUILTIN="stop-sign"/>
|
||||
<node CREATED="1584888403457" ID="ID_1500365619" MODIFIED="1584888425339" TEXT="Aufruf-Verfugung schwer verständlich">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
da weit über den Code verstreut
|
||||
|
|
@ -27659,9 +27649,7 @@
|
|||
</node>
|
||||
<node CREATED="1677775347540" ID="ID_483885409" MODIFIED="1677775363174" TEXT="Zeichenfehler damit behoben...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
es war der int vs double
|
||||
|
|
@ -30857,9 +30845,7 @@
|
|||
<node CREATED="1569709599619" ID="ID_195478308" MODIFIED="1569709628435" TEXT="aber die hierarchisch verschachtelten Komponenten sind auf ihn angewiesen"/>
|
||||
<node CREATED="1569709651932" ID="ID_1646518205" MODIFIED="1576282358053" TEXT="und es soll nicht...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<i><font color="#b4288e">everyone and my grandma does it this way... </font></i>
|
||||
|
|
@ -31296,9 +31282,7 @@
|
|||
<node CREATED="1566395384746" ID="ID_869767169" MODIFIED="1566395414266" TEXT="wir zeichnen nicht einen Stapel"/>
|
||||
<node CREATED="1566395415590" ID="ID_719677480" MODIFIED="1576282358051" TEXT="warum? Weil unsere Strukturen für letzteres zu komplex sind">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
gestapelte Strukturen dieser Komplexität lassen sich nicht durch Schattierung vermitteln.
|
||||
|
|
@ -35341,9 +35325,7 @@
|
|||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1663957087480" ID="ID_9335539" MODIFIED="1663957260417" TEXT="Frage wurde automatisch gelöscht">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<strong>If the question is more than <code>365</code> days old, and ...</strong>
|
||||
|
|
@ -37577,9 +37559,7 @@
|
|||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1614549430019" ID="ID_1189932533" MODIFIED="1614549464686" TEXT="das löst (nur) das Storage-Problem">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
insofern wir die Storage nur einmal, im jeweilgen CmdContext der Geste vorsehen müssen
|
||||
|
|
@ -38818,9 +38798,7 @@
|
|||
</node>
|
||||
<node CREATED="1619887333950" ID="ID_1150224022" MODIFIED="1619887725547" TEXT="ein Übersetzungs-Funktor braucht Platz">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Daher erscheint ein Adapter sinnvoll, der jeweils für eine einzelne Gesten-Instanz erzeugt wird. Dies erfordert jedoch Storage, welche ohne großen Overhead bereitgestellt und effizient genutzt sein will
|
||||
|
|
@ -39200,9 +39178,7 @@
|
|||
<node CREATED="1621021182357" ID="ID_22597166" MODIFIED="1621021189124" TEXT="und das Window verschieben wir ja nun"/>
|
||||
<node CREATED="1621021241365" ID="ID_426282812" MODIFIED="1621021322131" TEXT="Beobachtung: erst wenn wir verschieben, springen die Koordinaten alternierend">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...bevor die Trigger-Schwelle erreicht ist, wachsen sie schön monoton<br />...auch ist das Springen exakt alternierend, ein Schritt vor, ein Schritt zurück
|
||||
|
|
@ -39452,9 +39428,7 @@
|
|||
<node CREATED="1617569730283" ID="ID_1098298417" MODIFIED="1617569798116" TEXT="Modifier-Key auf der Tastatur"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1617569873288" ID="ID_32172316" MODIFIED="1617569973233" TEXT="Modus durch Tastenfolge aktiviert">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Beispiel: das "grab" von Blender ist ein praktisches Konzept. Dort kann man ein Element überhaupt nur bewegen, wenn man vorher die "g"-Taste gedrückt hatte. So etwas will ich in Lumiera auch haben... ist aber nicht so ganz einfach
|
||||
|
|
@ -39789,9 +39763,7 @@
|
|||
<node CREATED="1672695565677" ID="ID_74750688" MODIFIED="1672695578855" TEXT="dieser gilt ausnahmslos für alle Zeichen-Operationen"/>
|
||||
<node CREATED="1672695580626" ID="ID_1609686459" MODIFIED="1672695694973" TEXT="Lage kann sich durch Änderungen im Zoom-Window verschieben">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
beispielsweise wenn nach links über den bisherigen Ursprung hinaus gescrollt wird — dann wird (in Maßen) der Canvas vergrößert; dies invalidiert alle Koordinaten und das gesamte Layout, und anschließend bekommen aber alle Widgets und Zeichen-Routinen konsistent eine neue Canvas-Übersetzung
|
||||
|
|
@ -88292,12 +88264,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
Die Definition mit dem Frame als Basisklasse erscheint mir sauberer, denn sie legt zweifelsfrei fest, wo der Frame sein soll und daß er mit dem Anfang von HeteroData zusammenfallen soll. Außerdem dokumentiert das eine is-a Beziehung (wenngleich auch die Sichtbarkeit eingeschränkt ist).
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1733964348236" ID="ID_1028912337" MODIFIED="1733970622428" TEXT="damit funktioniert der Test ⟹ meine Spezialisierung als Solche war korrekt"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1733964371585" ID="ID_440070050" MODIFIED="1733964386475" TEXT="warum wird dann trotzdem der Tuple-Overload gewählt?">
|
||||
<node COLOR="#435e98" CREATED="1733964371585" ID="ID_440070050" MODIFIED="1734014199525" TEXT="warum wird dann trotzdem der Tuple-Overload gewählt?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1733970706145" ID="ID_1987504943" MODIFIED="1733970763130" TEXT="Overload-Resolution">
|
||||
<node CREATED="1733970768481" ID="ID_1455689693" MODIFIED="1733970773841" TEXT="drei Phasen">
|
||||
|
|
@ -88316,7 +88287,108 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node CREATED="1733972793050" ID="ID_1370589924" MODIFIED="1733972813148" TEXT="im einfachen Beispiel verhält sich alles wie erwartet...">
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
<node CREATED="1733976104485" ID="ID_1611524075" MODIFIED="1733976142755" TEXT="also dann ⟶ das Test-Stetup auf lib::HeteroData ausweiten...."/>
|
||||
<node CREATED="1733976143600" ID="ID_1376491238" MODIFIED="1733976159145" TEXT="Überraschung: unser Overload wird verwendet"/>
|
||||
<node CREATED="1733976227876" ID="ID_1241183034" MODIFIED="1733976251028" TEXT="selbst bei einem HeteroData mit zwei Storage-Frames (genau wie im HeteroData_test)"/>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1733976161057" ID="ID_764085376" MODIFIED="1733976313682" TEXT="aber nur im ersten Block — sobald der Index in den Chain-Block zeigt ⟹ ��">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1733976359562" ID="ID_560828575" MODIFIED="1733976368941" TEXT="jetzt wirds aber wild....">
|
||||
<node CREATED="1733976374289" ID="ID_1987690737" MODIFIED="1733976531838" TEXT="std::get<1>(chain2) ⟶ unser Code (funktioniert!)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ja wirklich: der Code geht durch den Compiler und zur Laufzeit kann ich mit dem Debugger in unseren Overload steppen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1733976405948" ID="ID_558042856" MODIFIED="1733976504495" TEXT="std::get<2>(chain2) ⟶ compile-time-Assertion ⟹ std::tuple-Overload">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ja wirklich: man sieht das am Error-Stack der Compile-Fehlermeldung; der Einstieg ging sofort in den Code aus der Stdlib (tuple.h, 1335)
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1733976996794" ID="ID_1396891623" MODIFIED="1733977038241" TEXT="exakt diese Funktionen unter anderem Namen ⟹ Fehler im Test-Setup reproduzierbar">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1733977452943" ID="ID_1506713776" MODIFIED="1733977494203" TEXT="die Assertion-Failure kommt aus tuple_element_t<I,tuple>">
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1733977495974" ID="ID_111800552" MODIFIED="1733977527259" TEXT="das ist die Return-Typ-Spezifikation (die damit den Bounds-Check macht)"/>
|
||||
<node CREATED="1733977563599" ID="ID_1211995842" MODIFIED="1733977631314">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
durch decltype(auto) ersetzt ⟹ compiliert und <b>unser Overload</b> wird genommen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#fafe99" COLOR="#7c13ac" CREATED="1733977636822" ID="ID_1077880173" MODIFIED="1734014031096" TEXT="die std::get-Implementierung ist problematisch">
|
||||
<icon BUILTIN="broken-line"/>
|
||||
<node CREATED="1733977693106" HGAP="24" ID="ID_836532737" MODIFIED="1733977843731" TEXT="Compiler bricht bereits vor der Overload-Resolution ab!" VSHIFT="15">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
denn würde er dorthin kommen, dann würde er unseren Overload tatsächlich wählen, exakt wie erwartet; und unser Overload würde auch funktionieren.
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1733977777950" ID="ID_1937163989" MODIFIED="1733977989370" TEXT="das kann durchaus ein Defekt in der Lib-Impl sein">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Ich verwende ja einen <i>uralten Compiler</i> und eine OS-Version, die schon am Ende der Lebensdauer ist; gut möglich, daß dieses Problem anderswo längst erkannt und behoben wurde — es würde ja bereits genügen, die assertion erst im Body der Funktion zu haben, denn dann könnte die Overload-Resolution arbeiten und daran vorbeikommen. Andererseits ist die Assertion grundsätzlich in Ordnung, denn <i>falls es hier keine custom-Version gäbe</i>, wäre der Aufruf ja tatsächlich gefährlich und müßte verhindert werden
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1734014085401" ID="ID_1101168757" MODIFIED="1734014196485">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<u>Fazit</u>: Overload-Resolution ist gar nicht das Problem
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
unser Overload ist in Ordnung, wird vom Compiler gewählt und funktioniert fehlerfrei.... wenn da nur nicht die Implementierung von std::get wäre, welche bereits bei der Instantiierung mit konkreten Parametern eine Assertion triggert und damit die Compilierung stoppt.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1734014214885" ID="ID_972712516" MODIFIED="1734014234674" TEXT="Zum Stand">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="12"/>
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1734014236281" ID="ID_1176641246" MODIFIED="1734014246708" TEXT="unsere custom-Implementierung ist in Ordnung"/>
|
||||
<node CREATED="1734014247626" ID="ID_456472930" MODIFIED="1734014267450" TEXT="aber wegen der Implementierung von std::get haben wir praktisch keine Chance"/>
|
||||
<node CREATED="1734014280187" ID="ID_1101163116" MODIFIED="1734014286536" TEXT="man kann das Problem nur umgehen">
|
||||
<node CREATED="1734014287759" ID="ID_1313304599" MODIFIED="1734014318718" TEXT="auf die Vererbung verzichten �� anderweitig sehr problematisch"/>
|
||||
<node CREATED="1734014322719" ID="ID_916809252" MODIFIED="1734014356341" TEXT="mit einer freien get-Funktion im Namespace arbeiten"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue