220 35290 <69b63819-3410-4662-8728-194f784aca17@isocpp.org> article
Path: news.gmane.org!.POSTED!not-for-mail
From: ambrop7@gmail.com
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: Overriding virtual functions of member class
Date: Tue, 7 Nov 2017 12:20:06 -0800 (PST)
Lines: 447
Approved: news@gmane.org
Message-ID: <69b63819-3410-4662-8728-194f784aca17@isocpp.org>
References: <26216c34-9ff6-435b-8da5-9b21460fee1c@isocpp.org> <ef837718-0421-4780-948c-cc0c897cbcf8@isocpp.org> <d52fd84c-984f-44d3-a956-86e4c5217cc7@isocpp.org>
 <3038266.teaS50zGzH@tjmaciei-mobl1>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_52_938211203.1510086006930"
X-Trace: blaine.gmane.org 1510086008 25267 195.159.176.226 (7 Nov 2017 20:20:08 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Tue, 7 Nov 2017 20:20:08 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBDSJLPGLZMPBB6FKRDIAKGQEYTPWYFI@isocpp.org Tue Nov 07 21:20:03 2017
Return-path: <std-proposals+bncBDSJLPGLZMPBB6FKRDIAKGQEYTPWYFI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-ua0-f200.google.com ([209.85.217.200])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBDSJLPGLZMPBB6FKRDIAKGQEYTPWYFI@isocpp.org>)
	id 1eCALq-0006K7-E0
	for gclcip-std-proposals@m.gmane.org; Tue, 07 Nov 2017 21:20:02 +0100
Original-Received: by mail-ua0-f200.google.com with SMTP id w32sf226836uaw.23
        for <gclcip-std-proposals@m.gmane.org>; Tue, 07 Nov 2017 12:20:10 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=3F5KzkhlPDmTwbkkQr0sTYUXyXdggk+D7t7k+4p5580=;
        b=GUTiO14cX7ReWY56dUTjTJsdYZ8W2fTqjhARedD/0154jslQ00lqhOvzZJB7Yi8zfr
         TfAeUmUohjJfi/nB3Apsot78sBlUdqTJCJIQekTcBRetD0UNybB2YHEh6i3XdG/ieggo
         9H4v6oqrIOyKv3xEHkG411x69kFkGjgwo0Mn2xaLBWXVLXYGvRkX7BNkwybn1GMCovXD
         k7MnFMkRafFVgoIn3iN5oXV+1gAab7CzBZiXA9SiK/AjCzipPqHjHee3xVDLJmzTPpYn
         rhjnJ2BaScFEqyynBbda5Pk/RWtsF94ICEu7QnVxGQD1znSqMeDHs8BPRmDuur21xQyz
         Bl7Q==
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20161025;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :x-original-sender:reply-to:precedence:mailing-list:list-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=3F5KzkhlPDmTwbkkQr0sTYUXyXdggk+D7t7k+4p5580=;
        b=rhC/nPBiy9lhc38spsB1CPNOyQoCqpfgnjqfVG0fdipTma7SfEYm1d5F2mT/rp/z2H
         mys8FZhmMDIpf+WqpaL5QHgh4U8YexZw/aVB5XgDghL+SWsBpvkrtIgJi5rYbnVRIW4G
         ezV1vUul1WWEYKDf436H5drbjOsj9Tv4krknf0WiJO+HpJ26DQ7bMccmyM5NWc4vqwN0
         Aeq1upt/DUAo1nFBvZN5Lb0lgom5LihhRb+IzBLAqA6svBVPp4JnlDFQUzI3wGNBwK7u
         UUgTdr6rq3A+6f8jdPxXJGvNr7U64jpfndBWMHp67QKb6/e3j+5blxv/VhS8dG0od0rW
         w+7A==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:x-original-sender:reply-to:precedence
         :mailing-list:list-id:x-spam-checked-in-group:list-post:list-help
         :list-archive:list-subscribe:list-unsubscribe;
        bh=3F5KzkhlPDmTwbkkQr0sTYUXyXdggk+D7t7k+4p5580=;
        b=J8WYqj1jYp27vIpv+0RVFKxB5jwLdfcVgMFWu35GZLInPXkVGsgNzWUlmwWbov9uy7
         XppQtmm5sRvSlvkzoyfYaC9G5dhkbFPHsXAe9oNJLVq+kr15bFNFFxfgOfj0sfWgqj7z
         GAMOcR7HcMZe+yb+kEIchJRJmEB+5971G0RbbbBx3IJh2tGlwu0RJQy0d64OrjBx+S8D
         +RP02ARiytZm4gyb1q9V4Mru/GJI0XkjZ7y6gvhMhxOq1A9flGuGHyUKCOiqenCB3x0R
         bNa1Q6Z91arcpJWfHGV76+fFDUEpVQXdFmivpS11VUdUnuyY347LSIsjv6T2NOSEPO+h
         4CEg==
X-Gm-Message-State: AMCzsaUTj9OTS08EUjhzAdqJrHhNFZJfc7rcOQPldrtpjkL2QfSypBZr
	SLNw8Swqx3Zikj5eizBO4MfSnw==
X-Google-Smtp-Source: ABhQp+Qj9awnREgCCVrOKKiyf1sNpar8WTus8dPsTvzCzqrYEHs5D48fZEnzMLRgMJIkYo9zMqqhKA==
X-Received: by 10.159.59.212 with SMTP id y20mr11393998uah.1.1510086009508;
        Tue, 07 Nov 2017 12:20:09 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.176.75.129 with SMTP id v1ls5222308uaf.18.gmail; Tue, 07 Nov
 2017 12:20:08 -0800 (PST)
X-Received: by 10.31.201.198 with SMTP id z189mr1670334vkf.0.1510086007856;
        Tue, 07 Nov 2017 12:20:07 -0800 (PST)
In-Reply-To: <3038266.teaS50zGzH@tjmaciei-mobl1>
X-Original-Sender: ambrop7@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Google-Group-Id: 399137483710
List-Post: <https://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <https://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <https://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <https://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:35290
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/35290>

------=_Part_52_938211203.1510086006930
Content-Type: multipart/alternative; 
	boundary="----=_Part_53_298471831.1510086006930"

------=_Part_53_298471831.1510086006930
Content-Type: text/plain; charset="UTF-8"

@Bengt, please see my comments to your proposal below!

> In my code I would probably try to write something like this:
> OP, what happens if you try this? Do you get the perfect codegen you're 
expecting? Do you care about pursuing your core-language proposal any 
further?

I am aware of this solution and have been using it in a few places. It is 
good from the performance perspective, but I am still invested in improving 
the language to make this easier. The worst problem with this solution is 
that such a wrapper would be needed for *every* class that has callbacks, 
which is a lot of boilerplate.

> > This sounds *exactly* like private inheritance. Private inheritance 
gives 
> you all of the above, without exporting an "IS-A" relationship to the 
> outside world. 

But it does make the class name visible for the purpose of name resolution. 
For example, assume that class A privately inherits Timer and:
- Class B inherits A and privately inherits Timer (the same one), you will 
get compile errors due to "ambiguous base class".
- Class B inherits A and uses the name Timer somewhere meaning to refer to 
a Timer type outside the B class (a different type than Timer inherited by 
A), but this will actually refer to the Timer type privately inherited by A.

I personally consider this visibility of private bases a design defect but 
it is what it is.

> 
> But you can't multiply inherit from the same class. 
> Of course, we can always apply the fundamental theorem of software 
engineering:

This solution turns every virtual call into two virtual calls, reducing 
performance. The static_cast + friend function approach proposed by Arthur 
solves this, irrespective of whether you have a wrapper template or 
hand-code the derived classes.

On Monday, November 6, 2017 at 11:22:45 PM UTC+1, Bengt Gustafsson wrote:
>
> I agree with the intention of this proposal: ...
>

Thank you for your comments, I appreciate that someone also thinks the 
situation should be improved.

Given that it has to have a vtable anyway this is going to be relatively 
> cheap to add the type_info instance.
>
Yes, giving it its own typeinfo is not a problem at all, whatever the 
syntax is.
 

> The original proposal handles b) by viewing the implementation as being a 
> method of the outer class rather than the subobject. This is a bit awkward 
> as it does not allow access to the members of the subobject without 
> prepending their names with the subobject name.
>
I don't see a problem with having to type m_a if you want to access the 
subobject's members from the overridden function. It's good to be explicit, 
the code length difference would be minor unless you really like long 
member names. And I think in practice you would be accessing other objects 
more frequently than the calling one, as in my Client example. Probably the 
reason for this is that the callback just gave you something new to work 
with and the next step is likely to do something with this possibly with 
the assistance of other objects.
 

>
> This means that the main requisites are fulfilled. The remaning problem 
> is, in my mind, clarity. There is no mentioning that the A m_a; declaration 
> is not just a plain old A close to its declaration, the method overrides 
> can be anywhere in the class head.
>
If you use private inheritance, the method overrides can also be anywhere, 
they don't and can't be at the site where you specified the base class, so 
I am not bothered that in my originally proposed design the overrides are 
not at the site where you declared the member. However I agree that "there 
is no mentioning that the A m_a; declaration is not just a plain old A 
close to its declaration".

The main issue I have with this is that the method overrides are not 
> written inside the class head of the class being created. This creates a 
> lot of unnecessary confusion. The solution close at hand seems to be an 
> anonymous class declaration:
>
>  
> class Client {
>     class : public Timer {
>         void timerExpired() override {
>             Client::m_client_manager.clientDisconnected(*Client::this);
>         }
>     } m_timer;  // As the subclass has no name we know there will be no 
> more instances.
> };
>
>
>
I would like at least the ability have the function body inside the 
containing class, often that just makes more sense. For example consider 
the Client/DatabaseAccess interaction, a function in Client initiated a 
query so it looks right if a function in Client handles the result.
 

> The weak part of this suggestion is probably the access of outer class 
> members (including this) using a class scope prefix. This seems like 
> mutliple inheritance except that you can't inherit from the outer class in 
> the inner class' declaration as it is incomplete by necessity. It may also 
> seem like this syntax would be usable in any nested class, which of course 
> it can't be. Unless... a way to achieve general inner class functionality 
> is to allow inheriting from the surrounding class using indirect 
> inheritance. This case would then become a special case of that feature and 
> the problem of how to access the outer object is just moved to the cast 
> operator to the outer class. Furthermore a new set of boilerplate is 
> introduced which reduces the appeal of the functionality. One obscure way 
> to create a syntax for the this pointer of the containing class is to 
> redefine this from being a pointer to being an array. Thanks to C++ array 
> to pointer conversion this would still work as usual but would now have an 
> operator[] to reach the outer class.
>
> Combining these features and indicating indirect inheritance with a 
> combination of virtual inheritance and a cast operator to the same class we 
> get:
>
> class Client {
>      class : Timer, virtual Client {   // Reversed multiple inheritance 
> motivates accessing Client members directly.
>           operator Client&() { return this[1]; }  // Mysterious 
> boilerplate...
>           void timerExpired() override {
>                m_client_manager.clientDisconnected(*this);
>           }
>      } m_a;
>      ClientManager& m_client_manager;
> };
>
>
I see the following issues with this idea:
1) "virtual" no longer means virtual base, the meaning of virtual bases 
changes based on "Mysterious boilerplate" present in the class.
2) this[1] syntax gives no indication of the meaning.
3) One cannot easily implement the overridden functions as members of the 
containing class, if you want that you will have to write boilerplate to 
forward each call.

I have a proposal which is an elaboration on this idea:
- Use a specific keyword, for example "member", in the declaration of the 
class, e.g. "member class : Timer { ... } m_timer;". This differentiates 
normal class declarations from this new feature where the class is a single 
member and has access to its container.
- Functions in the nested class have access to the containing class as if 
the containing class was some kind of base (but it's not). This includes 
ability to static_cast<ContainingClass*>(this).
- Allow mapping callbacks to functions of the containing class by using 
"=", e.g. "void timerExpired() override = Client::timerExpired;". Perhaps 
also allow "auto" type to avoid having to write the arguments and return 
type twice.

Here is how it would look like, with the different kinds of callback 
declarations (all permitted):
class Client {
    member class : Timer {
        // Implementation in nested class.
        void timerExpired() override {
            // implicit access to Client members is possible
            m_client_manager.clientDisconnected(*this);
        }
        
        // Implementation in containing class, full signature.
        void timerExpired() override = Client::timerExpired;
        
        // Implementation in containing class, signature deduced.
        auto timerExpired override = Client::timerExpired;
    } m_timer;
    
    void timerExpired() {
        m_client_manager.clientDisconnected(*this);
    }
};

-- 
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/69b63819-3410-4662-8728-194f784aca17%40isocpp.org.

------=_Part_53_298471831.1510086006930
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>@Bengt, please see my comments to your proposal below=
!</div><div><br></div><div>&gt; In my code I would probably try to write so=
mething like this:</div><div>&gt; OP, what happens if you try this? Do you =
get the perfect codegen you&#39;re expecting? Do you care about pursuing yo=
ur core-language proposal any further?</div><div><br></div><div>I am aware =
of this solution and have been using it in a few places. It is good from th=
e performance perspective, but I am still invested in improving the languag=
e to make this easier. The worst problem with this solution is that such a =
wrapper would be needed for *every* class that has callbacks, which is a lo=
t of boilerplate.</div><div><br></div><div>&gt; &gt; This sounds *exactly* =
like private inheritance. Private inheritance gives=C2=A0<br>&gt; you all o=
f the above, without exporting an &quot;IS-A&quot; relationship to the=C2=
=A0<br>&gt; outside world.=C2=A0</div><div><br></div><div>But it does make =
the class name visible for the purpose of name resolution. For example, ass=
ume that class A privately inherits Timer and:</div><div>- Class B inherits=
 A and privately inherits Timer (the same one), you will get compile errors=
 due to &quot;ambiguous base class&quot;.</div><div>- Class B inherits A an=
d uses the name Timer somewhere meaning to refer to a Timer type outside th=
e B class (a different type than Timer inherited by A), but this will actua=
lly refer to the Timer type privately inherited by A.</div><div><br></div><=
div>I personally consider this visibility of private bases a design defect =
but it is what it is.</div><div><br>&gt;=C2=A0<br>&gt;=C2=A0But you can&#39=
;t multiply inherit from the same class.=C2=A0<br></div><div>&gt; Of course=
, we can always apply the fundamental theorem of software engineering:</div=
><div><br></div><div>This solution turns every virtual call into two virtua=
l calls, reducing performance. The static_cast + friend function approach p=
roposed by Arthur solves this, irrespective of whether you have a wrapper t=
emplate or hand-code the derived classes.</div><div><br></div><div>On Monda=
y, November 6, 2017 at 11:22:45 PM UTC+1, Bengt Gustafsson wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1p=
x solid rgb(204, 204, 204); padding-left: 1ex;"><div dir=3D"ltr">I agree wi=
th the intention of this proposal: ...</div></blockquote><div><br></div><di=
v>Thank you for your comments, I appreciate that someone also thinks the si=
tuation should be improved.</div><div><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, =
204, 204); padding-left: 1ex;"><div dir=3D"ltr">Given that it has to have a=
 vtable anyway this is going to be relatively cheap to add the type_info in=
stance.</div></blockquote><div>Yes, giving it its own typeinfo is not a pro=
blem at all, whatever the syntax is.</div><div>=C2=A0</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px soli=
d rgb(204, 204, 204); padding-left: 1ex;"><div dir=3D"ltr"><div>The origina=
l proposal handles b) by viewing the implementation as being a method of th=
e outer class rather than the subobject. This is a bit awkward as it does n=
ot allow access to the members of the subobject without prepending their na=
mes with the subobject name.</div></div></blockquote><div>I don&#39;t see a=
 problem with having to type m_a if you want to access the subobject&#39;s =
members from the overridden function. It&#39;s good to be explicit, the cod=
e length difference would be minor unless you really like long member names=
.. And I think in practice you would be accessing other objects more frequen=
tly than the calling one, as in my Client example. Probably the reason for =
this is that the callback just gave you something new to work with and the =
next step is likely to do something with this possibly with the assistance =
of other objects.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204=
); padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>This means that=
 the main requisites are fulfilled. The remaning problem is, in my mind, cl=
arity. There is no mentioning that the A m_a; declaration is not just a pla=
in old A close to its declaration, the method overrides can be anywhere in =
the class head.</div></div></blockquote><div>If you use private inheritance=
, the method overrides can also be anywhere, they don&#39;t and can&#39;t b=
e at the site where you specified the base class, so I am not bothered that=
 in my originally proposed design the overrides are not at the site where y=
ou declared the member. However I agree that &quot;there is no mentioning t=
hat the A m_a; declaration is not just a plain old A close to its declarati=
on&quot;.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding=
-left: 1ex;"><div dir=3D"ltr"><div>The main issue I have with this is that =
the method overrides are not written inside the class head of the class bei=
ng created. This creates a lot of unnecessary confusion. The solution close=
 at hand seems to be an anonymous class declaration:</div><div><br></div><d=
iv>=C2=A0</div><div style=3D"border-width: 1px; border-style: solid; border=
-color: rgb(187, 187, 187); background-color: rgb(250, 250, 250); word-wrap=
: break-word;"><code><span style=3D"color: rgb(0, 0, 136);">class</span><sp=
an style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(10=
2, 0, 102);">Client</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span=
><span style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb=
(0, 0, 0);"><br>=C2=A0 =C2=A0=C2=A0</span><span style=3D"color: rgb(0, 0, 1=
36);">class</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span s=
tyle=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0, 0=
);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">public</span><span =
style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, =
0, 102);">Timer</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><sp=
an style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, =
0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0</span><span style=3D"color: r=
gb(0, 0, 136);">void</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0timer=
Expired</span><span style=3D"color: rgb(102, 102, 0);">()</span><span style=
=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(0, 0, 136)=
;">override</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span s=
tyle=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0=
);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0</span><span style=
=3D"color: rgb(102, 0, 102);">Client</span><span style=3D"color: rgb(102, 1=
02, 0);">::</span><span style=3D"color: rgb(0, 0, 0);">m_client_manager</sp=
an><span style=3D"color: rgb(102, 102, 0);">.</span><span style=3D"color: r=
gb(0, 0, 0);">clien<wbr>tDisconnected</span><span style=3D"color: rgb(102, =
102, 0);">(*</span><span style=3D"color: rgb(102, 0, 102);">Client</span><s=
pan style=3D"color: rgb(102, 102, 0);">::</span><span style=3D"color: rgb(0=
, 0, 136);">this</span><span style=3D"color: rgb(102, 102, 0);">);</span><s=
pan style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0</s=
pan><span style=3D"color: rgb(102, 102, 0);">}</span><span style=3D"color: =
rgb(0, 0, 0);"><br>=C2=A0 =C2=A0=C2=A0</span><span style=3D"color: rgb(102,=
 102, 0);">}</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0m_timer</span=
><span style=3D"color: rgb(102, 102, 0);">;</span><span style=3D"color: rgb=
(0, 0, 0);">=C2=A0=C2=A0</span><span style=3D"color: rgb(136, 0, 0);">// As=
 the subclass has no name we know there will be no more instances.</span><s=
pan 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><br></span></=
code></div><div><br></div></div></blockquote><div><br></div><div>I would li=
ke at least the ability have the function body inside the containing class,=
 often that just makes more sense. For example consider the Client/Database=
Access interaction, a function in Client initiated a query so it looks righ=
t if a function in Client handles the result.</div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left:=
 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div dir=3D"ltr"><div></=
div><div>The weak part of this suggestion is probably the access of outer c=
lass members (including this) using a class scope prefix. This seems like m=
utliple inheritance except that you can&#39;t inherit from the outer class =
in the inner class&#39; declaration as it is incomplete by necessity. It ma=
y also seem like this syntax would be usable in any nested class, which of =
course it can&#39;t be. Unless... a way to achieve general inner class func=
tionality is to allow inheriting from the surrounding class using indirect =
inheritance. This case would then become a special case of that feature and=
 the problem of how to access the outer object is just moved to the cast op=
erator to the outer class. Furthermore a new set of boilerplate is introduc=
ed which reduces the appeal of the functionality. One obscure way to create=
 a syntax for the this pointer of the containing class is to redefine this =
from being a pointer to being an array. Thanks to C++ array to pointer conv=
ersion this would still work as usual but would now have an operator[] to r=
each the outer class.</div><div><br></div><div>Combining these features and=
 indicating indirect inheritance with a combination of virtual inheritance =
and a cast operator to the same class we get:</div><div><br></div><div styl=
e=3D"border-width: 1px; border-style: solid; border-color: rgb(187, 187, 18=
7); background-color: rgb(250, 250, 250); word-wrap: break-word;"><code><sp=
an style=3D"color: rgb(0, 0, 136);">class</span><span style=3D"color: rgb(0=
, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 0, 102);">Client</spa=
n><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: r=
gb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color: rgb(0, 0, 136);">class</span><spa=
n style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102=
, 102, 0);">:</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span=
 style=3D"color: rgb(102, 0, 102);">Timer</span><span style=3D"color: rgb(1=
02, 102, 0);">,</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><sp=
an style=3D"color: rgb(0, 0, 136);">virtual</span><span style=3D"color: rgb=
(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 0, 102);">Client</s=
pan><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color:=
 rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0=C2=
=A0=C2=A0</span><span style=3D"color: rgb(136, 0, 0);">// Reversed multiple=
 inheritance motivates accessing Client members directly.</span><span style=
=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0</spa=
n><span style=3D"color: rgb(0, 0, 136);">operator</span><span style=3D"colo=
r: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 0, 102);">Cli=
ent</span><span style=3D"color: rgb(102, 102, 0);">&amp;()</span><span styl=
e=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102,=
 0);">{</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=
=3D"color: rgb(0, 0, 136);">return</span><span style=3D"color: rgb(0, 0, 0)=
;">=C2=A0</span><span style=3D"color: rgb(0, 0, 136);">this</span><span sty=
le=3D"color: rgb(102, 102, 0);">[</span><span style=3D"color: rgb(0, 102, 1=
02);">1</span><span style=3D"color: rgb(102, 102, 0);">];</span><span style=
=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, =
0);">}</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0=C2=A0</span><span =
style=3D"color: rgb(136, 0, 0);">// Mysterious boilerplate...</span><span s=
tyle=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0<=
/span><span style=3D"color: rgb(0, 0, 136);">void</span><span style=3D"colo=
r: rgb(0, 0, 0);">=C2=A0timerExpired</span><span style=3D"color: rgb(102, 1=
02, 0);">()</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span s=
tyle=3D"color: rgb(0, 0, 136);">override</span><span style=3D"color: rgb(0,=
 0, 0);">=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">{</span><spa=
n style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0m_client_manager</span><span style=3D"color: rgb(102, 102,=
 0);">.</span><span style=3D"color: rgb(0, 0, 0);">clientDiscon<wbr>nected<=
/span><span style=3D"color: rgb(102, 102, 0);">(*</span><span style=3D"colo=
r: rgb(0, 0, 136);">this</span><span style=3D"color: rgb(102, 102, 0);">);<=
/span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0=C2=A0</span><span style=3D"color: rgb(102, 102, 0);">}</span><span s=
tyle=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D=
"color: rgb(102, 102, 0);">}</span><span style=3D"color: rgb(0, 0, 0);">=C2=
=A0m_a</span><span style=3D"color: rgb(102, 102, 0);">;</span><span style=
=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"col=
or: rgb(102, 0, 102);">ClientManager</span><span style=3D"color: rgb(102, 1=
02, 0);">&amp;</span><span style=3D"color: rgb(0, 0, 0);">=C2=A0m_client_ma=
nager</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><br></span></code></div><=
/div></blockquote><div><br></div><div>I see the following issues with this =
idea:</div><div>1) &quot;virtual&quot; no longer means virtual base, the me=
aning of virtual bases changes based on &quot;Mysterious boilerplate&quot; =
present in the class.</div><div>2) this[1] syntax gives no indication of th=
e meaning.</div><div>3) One cannot easily implement the overridden function=
s as members of the containing class, if you want that you will have to wri=
te boilerplate to forward each call.</div><div><br></div><div>I have a prop=
osal which is an elaboration on this idea:</div></div><div>- Use a specific=
 keyword, for example &quot;member&quot;, in the declaration of the class, =
e.g. &quot;member class : Timer { ... } m_timer;&quot;. This differentiates=
 normal class declarations from this new feature where the class is a singl=
e member and has access to its container.</div><div>- Functions in the nest=
ed class have access to the containing class as if the containing class was=
 some kind of base (but it&#39;s not). This includes ability to static_cast=
&lt;ContainingClass*&gt;(this).</div><div>- Allow mapping callbacks to func=
tions of the containing class by using &quot;=3D&quot;, e.g. &quot;void tim=
erExpired() override =3D Client::timerExpired;&quot;. Perhaps also allow &q=
uot;auto&quot; type to avoid having to write the arguments and return type =
twice.</div><div><br></div><div>Here is how it would look like, with the di=
fferent kinds of callback declarations (all permitted):</div><div><div clas=
s=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-col=
or: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: =
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><div=
 class=3D"subprettyprint">class Client {</div><div class=3D"subprettyprint"=
>=C2=A0 =C2=A0 member class : Timer {</div><div class=3D"subprettyprint">=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 // Implementation in nested class.</div><div cl=
ass=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 void timerExpired() over=
ride {</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 // implicit access to Client members is possible</div><div class=
=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 m_client_mana=
ger.clientDisconnected(*this);</div><div class=3D"subprettyprint">=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 }</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=
=A0 =C2=A0=C2=A0</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 // Implementation in containing class, full signature.</div><div cla=
ss=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 void timerExpired() overr=
ide =3D Client::timerExpired;</div><div class=3D"subprettyprint">=C2=A0 =C2=
=A0 =C2=A0 =C2=A0=C2=A0</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 // Implementation in containing class, signature deduced.</di=
v><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 auto timerExpir=
ed override =3D Client::timerExpired;</div><div class=3D"subprettyprint">=
=C2=A0 =C2=A0 } m_timer;</div><div class=3D"subprettyprint">=C2=A0 =C2=A0=
=C2=A0</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 void timerExpired()=
 {</div><div class=3D"subprettyprint">=C2=A0 =C2=A0 =C2=A0 =C2=A0 m_client_=
manager.clientDisconnected(*this);</div><div class=3D"subprettyprint">=C2=
=A0 =C2=A0 }</div><div class=3D"subprettyprint">};</div></div></code></div>=
<br></div><div></div></div>

<p></p>

-- <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 />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/69b63819-3410-4662-8728-194f784aca17%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/69b63819-3410-4662-8728-194f784aca17=
%40isocpp.org</a>.<br />

------=_Part_53_298471831.1510086006930--

------=_Part_52_938211203.1510086006930--

.
