Topic: Bodies for inherited constructors


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Tue, 22 Sep 2015 12:53:10 -0700 (PDT)
Raw View
------=_Part_895_2060432483.1442951590849
Content-Type: multipart/alternative;
 boundary="----=_Part_896_298216531.1442951590850"

------=_Part_896_298216531.1442951590850
Content-Type: text/plain; charset=UTF-8

Sometimes I have a base class with several constructors and I want to make
them all available in a derived class with the exact same arguments while
just adding some behavior to the body of the constructor to initialize the
derived class.

struct A {
 A(int, string) { /*initialize A*/ }
};

struct B : A {
 B(int i, string s) : A(i, s) { /* do other work to initialize B */ }
}

The above example is benign enough, but if A has many constructors this
quickly becomes tedious. Even worse, if A is changed then B will have to
also be changed.

One workaround is perfect forwarding:

struct A {
 A(int);
 A(string);
 A(double);
};

struct B : A {
 template <typename... Args>
  B(Args&&... args) : A(std::forward<Args>(args)...) { /* do extra work to
init B */ }
  B(const B&); //copy op
};

This approach is bad. First, the forwarding constructor can be chosen over
user defined move/copy operations which is probably not expected or
intended.  Also from a documentaiton perspective its pretty terrible
because the signature tells us nothing about what arguments are valid or
not. A documentation system like doxygen can in theory use inherited
constructors to generate documentation with the correct arguments but not
for a forwarding constructor like this.

A solution would be to allow adding a body to a using declaration for
inheriting a constructor.

struct B {
 int x;
 using A::A : x(0) { /* do extra work to init B */ }
};

Do you see reasons why such a construct would be a bad idea? Admittedly it
only solves a small problem. If you for example want all of A's
constructors with additional parameters to initialize the members of B,
you're still out of luck and have to write them all or use forwarding.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_896_298216531.1442951590850
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Sometimes=C2=A0I have a base class with several const=
ructors and I want to make them all available in a derived class with the e=
xact same arguments while just adding some behavior to the body of the cons=
tructor to initialize the derived class.</div><div>=C2=A0</div><div><div st=
yle=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; backgro=
und-color: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"pretty=
print"><div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 136);"=
 class=3D"styled-by-prettify">struct</span><span style=3D"color: rgb(0, 0, =
0);" class=3D"styled-by-prettify"> A </span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">{</span><span style=3D"color: rgb(0,=
 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0A</span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">string</span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><=
span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span=
><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/*init=
ialize A*/</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by=
-prettify">}</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-=
prettify"><br></span><span style=3D"color: rgb(102, 102, 0);" class=3D"styl=
ed-by-prettify">};</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"><br><br></span><span style=3D"color: rgb(0, 0, 136);" class=
=3D"styled-by-prettify">struct</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> B </span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">:</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> A </span><span style=3D"color: rgb(102, 10=
2, 0);" class=3D"styled-by-prettify">{</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify"><br>=C2=A0B</span><span style=3D"color:=
 rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: rgb(0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> i</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">string</span><span=
 style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> s</span><span=
 style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">:</span>=
<span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A</span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">i</spa=
n><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">,</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> s</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
)</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> =
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify=
">/* do other work to initialize B */</span><span style=3D"color: rgb(0, 0,=
 0);" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 1=
02, 0);" class=3D"styled-by-prettify">}</span><span style=3D"color: rgb(0, =
0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(1=
02, 102, 0);" class=3D"styled-by-prettify">}</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"><br></span></div></code></div><br=
>The above example is benign enough, but if A has many constructors this qu=
ickly becomes tedious. Even worse, if A is changed then B will have to also=
 be changed.</div><div>=C2=A0</div><div>One workaround is perfect forwardin=
g:</div><div>=C2=A0</div><div><div style=3D"border: 1px solid rgb(187, 187,=
 187); word-wrap: break-word; background-color: rgb(250, 250, 250);" class=
=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint">=
<span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">struct<=
/span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A =
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
><br>=C2=A0A</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled=
-by-prettify">(</span><span style=3D"color: rgb(0, 0, 136);" class=3D"style=
d-by-prettify">int</span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"><br>=C2=A0A</span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 13=
6);" class=3D"styled-by-prettify">string</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">);</span><span style=3D"color: rg=
b(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0A</span><span style=3D"=
color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">double</span><span=
 style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">);</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">};</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
<br></span><span style=3D"color: rgb(0, 0, 136);" class=3D"styled-by-pretti=
fy">struct</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"> B </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-=
by-prettify">:</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-b=
y-prettify"> A </span><span style=3D"color: rgb(102, 102, 0);" class=3D"sty=
led-by-prettify">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styl=
ed-by-prettify"><br>=C2=A0</span><span style=3D"color: rgb(0, 0, 136);" cla=
ss=3D"styled-by-prettify">template</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102,=
 0);" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: rgb(0, =
0, 136);" class=3D"styled-by-prettify">typename</span><span style=3D"color:=
 rgb(102, 102, 0);" class=3D"styled-by-prettify">...</span><span style=3D"c=
olor: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: rgb(102, 0, 102);" class=3D"styled-by-prettify">Args</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&gt;</span><span=
 style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0 B</=
span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">=
(</span><span style=3D"color: rgb(102, 0, 102);" class=3D"styled-by-prettif=
y">Args</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify">&amp;&amp;...</span><span style=3D"color: rgb(0, 0, 0);" class=3D"=
styled-by-prettify"> args</span><span style=3D"color: rgb(102, 102, 0);" cl=
ass=3D"styled-by-prettify">)</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">:</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> A</span><span style=3D"color: rgb(102, 102, 0)=
;" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb(0, 0, 0);=
" class=3D"styled-by-prettify">std</span><span style=3D"color: rgb(102, 102=
, 0);" class=3D"styled-by-prettify">::</span><span style=3D"color: rgb(0, 0=
, 0);" class=3D"styled-by-prettify">forward</span><span style=3D"color: rgb=
(102, 102, 0);" class=3D"styled-by-prettify">&lt;</span><span style=3D"colo=
r: rgb(102, 0, 102);" class=3D"styled-by-prettify">Args</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">&gt;(</span><spa=
n style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">args</span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">)...)</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{=
</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">/=
* do extra work to init B */</span><span style=3D"color: rgb(0, 0, 0);" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" =
class=3D"styled-by-prettify">}</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"><br>=C2=A0 B</span><span style=3D"color: rgb(10=
2, 102, 0);" class=3D"styled-by-prettify">(</span><span style=3D"color: rgb=
(0, 0, 136);" class=3D"styled-by-prettify">const</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify"> B</span><span style=3D"color=
: rgb(102, 102, 0);" class=3D"styled-by-prettify">&amp;);</span><span style=
=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=
=3D"color: rgb(136, 0, 0);" class=3D"styled-by-prettify">//copy op</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">};</s=
pan><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><=
/span></div></code></div><br>This approach is bad. First, the forwarding co=
nstructor can be chosen over user defined move/copy operations which is pro=
bably not expected or intended.=C2=A0 Also from a documentaiton perspective=
 its pretty terrible because the signature tells us nothing about what=C2=
=A0arguments are valid or not. A documentation system like doxygen=C2=A0can=
 in theory use=C2=A0inherited constructors to generate documentation with t=
he correct arguments=C2=A0but not for a forwarding constructor like this.</=
div><div><br>A solution would be to allow adding a body to a using declarat=
ion for inheriting a constructor.</div><div>=C2=A0</div><div><div style=3D"=
border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-col=
or: rgb(250, 250, 250);" class=3D"prettyprint"><code class=3D"prettyprint">=
<div class=3D"subprettyprint"><span style=3D"color: rgb(0, 0, 136);" class=
=3D"styled-by-prettify">struct</span><span style=3D"color: rgb(0, 0, 0);" c=
lass=3D"styled-by-prettify"> B </span><span style=3D"color: rgb(102, 102, 0=
);" class=3D"styled-by-prettify">{</span><span style=3D"color: rgb(0, 0, 0)=
;" class=3D"styled-by-prettify"><br>=C2=A0</span><span style=3D"color: rgb(=
0, 0, 136);" class=3D"styled-by-prettify">int</span><span style=3D"color: r=
gb(0, 0, 0);" class=3D"styled-by-prettify"> x</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">;</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=C2=A0</span><span style=
=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">using</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A</span><span =
style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">A </span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">:</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> x</span=
><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: rgb(0, 102, 102);" class=3D"styled-by-prettify">0=
</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify=
">)</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"=
> </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-pretti=
fy">/* do extra work to init B */</span><span style=3D"color: rgb(0, 0, 0);=
" class=3D"styled-by-prettify"> </span><span style=3D"color: rgb(102, 102, =
0);" class=3D"styled-by-prettify">}</span><span style=3D"color: rgb(0, 0, 0=
);" class=3D"styled-by-prettify"><br></span><span style=3D"color: rgb(102, =
102, 0);" class=3D"styled-by-prettify">};</span><span style=3D"color: rgb(0=
, 0, 0);" class=3D"styled-by-prettify"> <br></span></div></code></div></div=
><div>=C2=A0</div><div>Do you see reasons why such a construct would be a b=
ad idea? Admittedly it only solves a small problem. If you for example want=
 all of A&#39;s constructors with additional parameters to initialize the m=
embers of B, you&#39;re still out of luck and have to write them all or use=
 forwarding.</div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_896_298216531.1442951590850--
------=_Part_895_2060432483.1442951590849--

.


Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Tue, 22 Sep 2015 15:12:06 -0700 (PDT)
Raw View
------=_Part_6601_844661286.1442959926458
Content-Type: multipart/alternative;
 boundary="----=_Part_6602_673173406.1442959926459"

------=_Part_6602_673173406.1442959926459
Content-Type: text/plain; charset=UTF-8

On Tuesday, September 22, 2015 at 8:53:11 PM UTC+1, Matthew Fioravante
wrote:
>
> Sometimes I have a base class with several constructors and I want to make
> them all available in a derived class with the exact same arguments while
> just adding some behavior to the body of the constructor to initialize the
> derived class.
>
> struct A {
>  A(int, string) { /*initialize A*/ }
> };
>
> struct B : A {
>  B(int i, string s) : A(i, s) { /* do other work to initialize B */ }
> }
>
> The above example is benign enough, but if A has many constructors this
> quickly becomes tedious. Even worse, if A is changed then B will have to
> also be changed.
>
> One workaround is perfect forwarding:
>
> struct A {
>  A(int);
>  A(string);
>  A(double);
> };
>
> struct B : A {
>  template <typename... Args>
>   B(Args&&... args) : A(std::forward<Args>(args)...) { /* do extra work
> to init B */ }
>   B(const B&); //copy op
> };
>
> This approach is bad. First, the forwarding constructor can be chosen over
> user defined move/copy operations which is probably not expected or
> intended.  Also from a documentaiton perspective its pretty terrible
> because the signature tells us nothing about what arguments are valid or
> not. A documentation system like doxygen can in theory use inherited
> constructors to generate documentation with the correct arguments but not
> for a forwarding constructor like this.
>
> A solution would be to allow adding a body to a using declaration for
> inheriting a constructor.
>
> struct B {
>  int x;
>  using A::A : x(0) { /* do extra work to init B */ }
> };
>
> Do you see reasons why such a construct would be a bad idea? Admittedly it
> only solves a small problem. If you for example want all of A's
> constructors with additional parameters to initialize the members of B,
> you're still out of luck and have to write them all or use forwarding.
>


Two solutions:

use a separate base:

struct A { .... };
struct B_members { int x; B_base() : x(0) {} };

struct B : A, B_members {
using A::A;
};

NSMI:

struct B : A {
    using A::A;
    int x = 0;

};

you can get, ahem, creative with NSMI and lambdas and execute arbitrary
code.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_6602_673173406.1442959926459
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Tuesday, September 22, 2015 at 8:53:11 PM UTC+1, Matthew Fioravante wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Someti=
mes=C2=A0I have a base class with several constructors and I want to make t=
hem all available in a derived class with the exact same arguments while ju=
st adding some behavior to the body of the constructor to initialize the de=
rived class.</div><div>=C2=A0</div><div><div style=3D"border:1px solid rgb(=
187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"><code>=
<div><span style=3D"color:rgb(0,0,136)">struct</span><span style=3D"color:r=
gb(0,0,0)"> A </span><span style=3D"color:rgb(102,102,0)">{</span><span sty=
le=3D"color:rgb(0,0,0)"><br>=C2=A0A</span><span style=3D"color:rgb(102,102,=
0)">(</span><span style=3D"color:rgb(0,0,136)">int</span><span style=3D"col=
or:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> </span><span s=
tyle=3D"color:rgb(0,0,136)">string</span><span style=3D"color:rgb(102,102,0=
)">)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(136,0,0)">/*initialize A*/</span><span style=3D"color:rgb(0,0=
,0)"> </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"co=
lor:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">};</span><s=
pan style=3D"color:rgb(0,0,0)"><br><br></span><span style=3D"color:rgb(0,0,=
136)">struct</span><span style=3D"color:rgb(0,0,0)"> B </span><span style=
=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"> A </spa=
n><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0=
,0)"><br>=C2=A0B</span><span style=3D"color:rgb(102,102,0)">(</span><span s=
tyle=3D"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> i</=
span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(0,0,136)">string</span><span style=
=3D"color:rgb(0,0,0)"> s</span><span style=3D"color:rgb(102,102,0)">)</span=
><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,=
0)">:</span><span style=3D"color:rgb(0,0,0)"> A</span><span style=3D"color:=
rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">i</span><span styl=
e=3D"color:rgb(102,102,0)">,</span><span style=3D"color:rgb(0,0,0)"> s</spa=
n><span style=3D"color:rgb(102,102,0)">)</span><span style=3D"color:rgb(0,0=
,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"co=
lor:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">/* do other work=
 to initialize B */</span><span style=3D"color:rgb(0,0,0)"> </span><span st=
yle=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br><=
/span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb=
(0,0,0)"><br></span></div></code></div><br>The above example is benign enou=
gh, but if A has many constructors this quickly becomes tedious. Even worse=
, if A is changed then B will have to also be changed.</div><div>=C2=A0</di=
v><div>One workaround is perfect forwarding:</div><div>=C2=A0</div><div><di=
v style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;backgroun=
d-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">str=
uct</span><span style=3D"color:rgb(0,0,0)"> A </span><span style=3D"color:r=
gb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0A</span><=
span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,13=
6)">int</span><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"=
color:rgb(0,0,0)"><br>=C2=A0A</span><span style=3D"color:rgb(102,102,0)">(<=
/span><span style=3D"color:rgb(0,0,136)">string</span><span style=3D"color:=
rgb(102,102,0)">);</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0A</span=
><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,=
136)">double</span><span style=3D"color:rgb(102,102,0)">);</span><span styl=
e=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">};</=
span><span style=3D"color:rgb(0,0,0)"><br><br></span><span style=3D"color:r=
gb(0,0,136)">struct</span><span style=3D"color:rgb(0,0,0)"> B </span><span =
style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"> A =
</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0</span><span style=3D"color:rgb(0,0,136)">template</spa=
n><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102=
,0)">&lt;</span><span style=3D"color:rgb(0,0,136)">typename</span><span sty=
le=3D"color:rgb(102,102,0)">...</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:rg=
b(102,102,0)">&gt;</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 B</spa=
n><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102=
,0,102)">Args</span><span style=3D"color:rgb(102,102,0)">&amp;&amp;...</spa=
n><span style=3D"color:rgb(0,0,0)"> args</span><span style=3D"color:rgb(102=
,102,0)">)</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"co=
lor:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)"> A</span><span=
 style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">st=
d</span><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"color:=
rgb(0,0,0)">forward</span><span style=3D"color:rgb(102,102,0)">&lt;</span><=
span style=3D"color:rgb(102,0,102)">Args</span><span style=3D"color:rgb(102=
,102,0)">&gt;(</span><span style=3D"color:rgb(0,0,0)">args</span><span styl=
e=3D"color:rgb(102,102,0)">)...)</span><span style=3D"color:rgb(0,0,0)"> </=
span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">/* do extra work to init=
 B */</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:r=
gb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 B</span>=
<span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,0,1=
36)">const</span><span style=3D"color:rgb(0,0,0)"> B</span><span style=3D"c=
olor:rgb(102,102,0)">&amp;);</span><span style=3D"color:rgb(0,0,0)"> </span=
><span style=3D"color:rgb(136,0,0)">//copy op</span><span style=3D"color:rg=
b(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">};</span><span st=
yle=3D"color:rgb(0,0,0)"><br></span></div></code></div><br>This approach is=
 bad. First, the forwarding constructor can be chosen over user defined mov=
e/copy operations which is probably not expected or intended.=C2=A0 Also fr=
om a documentaiton perspective its pretty terrible because the signature te=
lls us nothing about what=C2=A0arguments are valid or not. A documentation =
system like doxygen=C2=A0can in theory use=C2=A0inherited constructors to g=
enerate documentation with the correct arguments=C2=A0but not for a forward=
ing constructor like this.</div><div><br>A solution would be to allow addin=
g a body to a using declaration for inheriting a constructor.</div><div>=C2=
=A0</div><div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:bre=
ak-word;background-color:rgb(250,250,250)"><code><div><span style=3D"color:=
rgb(0,0,136)">struct</span><span style=3D"color:rgb(0,0,0)"> B </span><span=
 style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"><b=
r>=C2=A0</span><span style=3D"color:rgb(0,0,136)">int</span><span style=3D"=
color:rgb(0,0,0)"> x</span><span style=3D"color:rgb(102,102,0)">;</span><sp=
an style=3D"color:rgb(0,0,0)"><br>=C2=A0</span><span style=3D"color:rgb(0,0=
,136)">using</span><span style=3D"color:rgb(0,0,0)"> A</span><span style=3D=
"color:rgb(102,102,0)">::</span><span style=3D"color:rgb(0,0,0)">A </span><=
span style=3D"color:rgb(102,102,0)">:</span><span style=3D"color:rgb(0,0,0)=
"> x</span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"colo=
r:rgb(0,102,102)">0</span><span style=3D"color:rgb(102,102,0)">)</span><spa=
n style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{=
</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(13=
6,0,0)">/* do extra work to init B */</span><span style=3D"color:rgb(0,0,0)=
"> </span><span style=3D"color:rgb(102,102,0)">}</span><span style=3D"color=
:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">};</span><span=
 style=3D"color:rgb(0,0,0)"> <br></span></div></code></div></div><div>=C2=
=A0</div><div>Do you see reasons why such a construct would be a bad idea? =
Admittedly it only solves a small problem. If you for example want all of A=
&#39;s constructors with additional parameters to initialize the members of=
 B, you&#39;re still out of luck and have to write them all or use forwardi=
ng.</div></div></blockquote><div><br><br>Two solutions:<br><br>use a separa=
te base:<br><br>struct A { .... };<br>struct B_members { int x; B_base() : =
x(0) {} };<br><br>struct B : A, B_members {<br>using A::A;<br>};<br><br>NSM=
I:<br><br>struct B : A {<br>=C2=A0=C2=A0=C2=A0 using A::A;<br>=C2=A0=C2=A0=
=C2=A0 int x =3D 0;<br><br>};<br><br>you can get, ahem, creative with NSMI =
and lambdas and execute arbitrary code.<br></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_6602_673173406.1442959926459--
------=_Part_6601_844661286.1442959926458--

.


Author: Matthew Fioravante <fmatthew5876@gmail.com>
Date: Tue, 22 Sep 2015 15:32:01 -0700 (PDT)
Raw View
------=_Part_2954_444324962.1442961121828
Content-Type: multipart/alternative;
 boundary="----=_Part_2955_1475970551.1442961121828"

------=_Part_2955_1475970551.1442961121828
Content-Type: text/plain; charset=UTF-8


On Tuesday, September 22, 2015 at 6:12:06 PM UTC-4, Giovanni Piero Deretta
wrote:
>
>
> Two solutions:
>
> use a separate base:
>
> struct A { .... };
> struct B_members { int x; B_base() : x(0) {} };
>
> struct B : A, B_members {
> using A::A;
> };
>

Clever, but if you need to mutate a member of A:: in the addon B::B logic
(which my use case does) then this approach does not work since B_members
won't have access to A.

Essentially, I want to do this:
struct A {
 //constructors
 Obj& obj();
};

struct B : A {
 B(/*Args*/) : A(/*forward args*/) { A::obj().do_something(); }
};



>
> NSMI:
>
> struct B : A {
>     using A::A;
>     int x = 0;
>
> };
>

If all you need to do is initialize a data member this is the obvious
solution. If you need to do something else in the constructor, this won't
work. Doing your logic in a lambda meant to initialize a data member would
work but it requires that B has at least 1 data member and its horribly
ugly.

Having an NSMI syntax for base classes could be another solution and make
your B_members proposal solve my problem.


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_2955_1475970551.1442961121828
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br>On Tuesday, September 22, 2015 at 6:12:06 PM UTC-4, Gi=
ovanni Piero Deretta wrote:<blockquote style=3D"margin: 0px 0px 0px 0.8ex; =
padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width=
: 1px; border-left-style: solid;" class=3D"gmail_quote"><div><br>Two soluti=
ons:<br><br>use a separate base:<br><br>struct A { .... };<br>struct B_memb=
ers { int x; B_base() : x(0) {} };<br><br>struct B : A, B_members {<br>usin=
g A::A;<br>};</div></blockquote><div>=C2=A0</div><div>Clever, but if you ne=
ed=C2=A0to mutate=C2=A0a member of=C2=A0A:: in the addon=C2=A0B::B logic (w=
hich my use case does) then this approach=C2=A0does not work since B_member=
s won&#39;t have access to A.</div><div>=C2=A0</div><div>Essentially, I wan=
t to do this:</div><div><div style=3D"border: 1px solid rgb(187, 187, 187);=
 word-wrap: break-word; background-color: rgb(250, 250, 250);" class=3D"pre=
ttyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span s=
tyle=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">struct</span><=
span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A </span>=
<span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</sp=
an><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
=C2=A0</span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-pret=
tify">//constructors</span><span style=3D"color: rgb(0, 0, 0);" class=3D"st=
yled-by-prettify"><br>=C2=A0</span><span style=3D"color: rgb(102, 0, 102);"=
 class=3D"styled-by-prettify">Obj</span><span style=3D"color: rgb(102, 102,=
 0);" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: rgb(0,=
 0, 0);" class=3D"styled-by-prettify"> obj</span><span style=3D"color: rgb(=
102, 102, 0);" class=3D"styled-by-prettify">();</span><span style=3D"color:=
 rgb(0, 0, 0);" class=3D"styled-by-prettify"><br></span><span style=3D"colo=
r: rgb(102, 102, 0);" class=3D"styled-by-prettify">};</span><span style=3D"=
color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br><br></span><span sty=
le=3D"color: rgb(0, 0, 136);" class=3D"styled-by-prettify">struct</span><sp=
an style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> B </span><s=
pan style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">:</span=
><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A </spa=
n><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">{</=
span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify"><br>=
=C2=A0B</span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: rgb(136, 0, 0);" class=3D"styled-by-=
prettify">/*Args*/</span><span style=3D"color: rgb(102, 102, 0);" class=3D"=
styled-by-prettify">)</span><span style=3D"color: rgb(0, 0, 0);" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: rgb(102, 102, 0);" class=
=3D"styled-by-prettify">:</span><span style=3D"color: rgb(0, 0, 0);" class=
=3D"styled-by-prettify"> A</span><span style=3D"color: rgb(102, 102, 0);" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: rgb(136, 0, 0);" =
class=3D"styled-by-prettify">/*forward args*/</span><span style=3D"color: r=
gb(102, 102, 0);" class=3D"styled-by-prettify">)</span><span style=3D"color=
: rgb(0, 0, 0);" class=3D"styled-by-prettify"> </span><span style=3D"color:=
 rgb(102, 102, 0);" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: rgb(0, 0, 0);" class=3D"styled-by-prettify"> A</span><span style=3D"col=
or: rgb(102, 102, 0);" class=3D"styled-by-prettify">::</span><span style=3D=
"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">obj</span><span style=
=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">().</span><span =
style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">do_something</s=
pan><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettify">(=
);</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify">=
 </span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-prettif=
y">}</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: rgb(102, 102, 0);" class=3D"styled-by-pr=
ettify">};</span><span style=3D"color: rgb(0, 0, 0);" class=3D"styled-by-pr=
ettify"><br></span></div></code></div><br></div><div>=C2=A0</div><blockquot=
e style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color:=
 rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;" cla=
ss=3D"gmail_quote"><div><br>NSMI:<br><br>struct B : A {<br>=C2=A0=C2=A0=C2=
=A0 using A::A;<br>=C2=A0=C2=A0=C2=A0 int x =3D 0;<br><br>};</div></blockqu=
ote><div>=C2=A0</div><div>If all you need to do is initialize a data member=
 this is the obvious solution. If you need to do something else in the cons=
tructor, this won&#39;t work. Doing your logic in a lambda meant to initial=
ize a data member would work but it requires that B has at least 1 data mem=
ber and its horribly ugly.</div><div>=C2=A0</div><div>Having an NSMI syntax=
=C2=A0for base classes could be another solution and make your B_members pr=
oposal solve my problem.</div><div>=C2=A0</div></div>

<p></p>

-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_2955_1475970551.1442961121828--
------=_Part_2954_444324962.1442961121828--

.