From ce1ee71955eb7be95e4cab89f89720ed61e9d4e6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 8 Dec 2017 04:58:18 +0100 Subject: [PATCH] TreeExplorer: clarify base initialisation as it turned out, when "inheriting" ctors, C++14 removes the base classes' copy ctors. C++17 will rectify that. Thus for now we need to define explicitly that we'll accept the base for initialising the derived. But we need do so only on one location, namely the most down in the chain. --- src/lib/iter-source.hpp | 7 -- src/lib/iter-tree-explorer.hpp | 13 +- tests/library/iter-tree-explorer-test.cpp | 2 +- wiki/thinkPad.ichthyo.mm | 147 ++++++++++++++++++++-- 4 files changed, 144 insertions(+), 25 deletions(-) diff --git a/src/lib/iter-source.hpp b/src/lib/iter-source.hpp index 9a817e72a..2444d8aa1 100644 --- a/src/lib/iter-source.hpp +++ b/src/lib/iter-source.hpp @@ -143,14 +143,7 @@ namespace lib { : IterAdapter { using _I = IterAdapter; - using _I::IterAdapter; - iterator() =default; /////////////////////////////////////TICKET #1117 : why the hell do we need to declare all those ctor variants explicitly? I was under the impression ctor calls worked correct up to now without all this... - iterator(iterator&&) =default; - iterator(iterator const&) =default; - iterator(iterator& r) : iterator((iterator const&)r) { } - iterator& operator= (iterator &&) =default; - iterator& operator= (iterator const&) =default; operator string() const {return _I::source()? string(*_I::source()) : "⟂"; } }; diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 9d6d9e585..5339487ce 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -447,16 +447,17 @@ namespace lib { * call, where some "expansion layer" consumes the current element and replaces it by an expanded * series of new elements. Other layers might need to sync to this operation, and thus it is passed * down the chain. For that reason, we need a dedicated BaseAdapter to adsorb such chained calls. + * @remark when building the TreeExplorer, the to-be-wrapped source is fed down into its place + * within BaseAdapter. For that reason, we need to lift the copy ctors of the base. + * Just inheriting the base class ctors won't do that, at least not in C++14. */ template struct BaseAdapter : SRC { - using SRC::SRC; - BaseAdapter(SRC const& src) : SRC(src) { } ////////////////////////TODO why the hell do we need to redeclare all those ctor variants???? - BaseAdapter(SRC && src) : SRC(src) { } - BaseAdapter(SRC & src) : SRC(src) { } BaseAdapter() = default; + BaseAdapter(SRC const& src) : SRC(src) { } + BaseAdapter(SRC && src) : SRC(src) { } void expandChildren() { } }; @@ -781,10 +782,6 @@ namespace lib { /** pass-through ctor */ using SRC::SRC; - TreeExplorer(SRC const& src) : SRC(src) { } ////////////////////////TODO why the hell do we need to redeclare all those ctor variants???? why isn't copy initialisation propagated from the base ctors? - TreeExplorer(SRC && src) : SRC(src) { } - TreeExplorer(SRC & src) : SRC(src) { } - TreeExplorer() = default; diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 70047c815..c67d906a9 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -751,7 +751,7 @@ namespace test{ exploreIter = treeExplore(sequence) .filter([](int i){ return i>30; }) - .expand([](int i){ return CountDown{i-10, 20}; }) + .expand([](uint i){ return CountDown{i-10, 20}; }) .transform([](uint u) -> char { return '@'+u-20; }) .asIterSource(); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 1bc8dfbcf..2c95fb1f9 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -6035,18 +6035,147 @@ - - - - + + + + + + + + + + + +

+ ...da gibt es eine explizite Ausnahme-Regel. +

+

+ Die Copy-Konstruktoren werden aus der Kandidaten-Menge entfernt. +

+

+ +

+

+ Grund ist, daß die default-Initialisierung der Member-Felder noch nicht hinrechend geklärt war. +

+

+ C++17 holt das nach +

+ + +
- - + + + + + + +

+ ...dort wird einfach on-demand in der Basisklasse nachgeschaut. +

+

+ Wenn dabei ein Basis-Copy-Ctor gezogen wird, dann wird eben default-Init für die Felder im abgeleiteten Objekt gemacht. +

+

+ Es gibt dann eine neue, explizite Regel, die verhindert, daß zufällig ein aus der Basis geerbter Ctor +

+

+ die Signatur eines Copy-ctors überdeckt +

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

+ Allerdings genügt es, dies an einer Stelle in der Kette zu ergänzen +

+ + +
+ + + + + +

+ ...und zwar genau dort, wo erstmals ein Basis-Objekt akzeptiert wird. +

+

+ Das ist bei uns im BaseAdapter, also der ersten Ebene über dem zu initialisierenden Basis-Objekt. +

+

+ Alle anderen Layer darüber reichen dann korrekt mit dem geerbten Ctor diese Initialisierung nach Unten. +

+ + +
+
+ + + + + + +

+ übrigens ist es im IterSource<T>::iterator nicht  notwendig +

+ + +
+ + + + + +

+ ...das war nur ein unnötiger Fix nach dem Gießkannen-Prinzip. +

+

+ +

+

+ Denn dieser Iterator soll niemals mit einem Basis-Objekt initialisiert werden, +

+

+ sondern stets von der IterSource-Builder-Funktion konstruiert. +

+

+ Und wenn man selber keinen Ctor in eine Klasse schreibt, sondern nur ctor-erbt, +

+

+ dann werden auch die Copy-Konstruktoren korrekt automatisch generiert. +

+ + +
+ +
+
+ + - - + + + + + + + + + + + + @@ -6364,7 +6493,7 @@ - +