220 30156 <CAHfn=+sJCyDr4sVhXK-9c9cn0JOdaWt7Fr1ejiCBVT7Ab=Ybew@mail.gmail.com> article
Path: news.gmane.org!.POSTED!not-for-mail
From: Eugenio Bargiacchi <svalorzen@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: A strong typedef syntax idea
Date: Mon, 2 Jan 2017 19:21:53 +0100
Lines: 1632
Approved: news@gmane.org
Message-ID: <CAHfn=+sJCyDr4sVhXK-9c9cn0JOdaWt7Fr1ejiCBVT7Ab=Ybew@mail.gmail.com>
References: <fd8eda2b-182f-4e32-8fda-c7f728e22fa2@isocpp.org>
 <9574d1c1-b3ff-b9ae-ceee-908a2b983278@wanadoo.fr> <CAHfn=+t0MkFNY4h=crQWvh=JT2nHt5k_LWnO=SzgGkL2Q=_bSw@mail.gmail.com>
 <f4a57116-c65b-94f4-51f2-e5cf8b4ff3ca@wanadoo.fr> <CAHfn=+tVBKZOMtpURNBDCEJijFL_J5s+ROrLwJfkRgGyWzZMgg@mail.gmail.com>
 <ef8190c7-f46f-cf76-7e45-2114a84eae27@wanadoo.fr> <CAHfn=+tEbHpzdtK40qS_tVUPfPyKnOft-ZXOTMTDezPDzS3fAw@mail.gmail.com>
 <9adc5a02-3209-bf63-a684-fb0272da56e0@wanadoo.fr> <CAHfn=+vZEjYakroOWxB8u+SCS=5uDGU5mdYpWpyCbD-qS-P3TQ@mail.gmail.com>
 <edb42928-1e58-ee22-79ce-0fedd07247f1@wanadoo.fr>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: blaine.gmane.org
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary=f403045dd9604a4623054520a069
X-Trace: blaine.gmane.org 1483381323 29806 195.159.176.226 (2 Jan 2017 18:22:03 GMT)
X-Complaints-To: usenet@blaine.gmane.org
NNTP-Posting-Date: Mon, 2 Jan 2017 18:22:03 +0000 (UTC)
To: "ISO C++ Standard - Future Proposals" <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCWJHLVBTMARBQVUVLBQKGQEDPYG2NQ@isocpp.org Mon Jan 02 19:21:56 2017
Return-path: <std-proposals+bncBCWJHLVBTMARBQVUVLBQKGQEDPYG2NQ@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-yw0-f200.google.com ([209.85.161.200])
	by blaine.gmane.org with esmtp (Exim 4.84_2)
	(envelope-from <std-proposals+bncBCWJHLVBTMARBQVUVLBQKGQEDPYG2NQ@isocpp.org>)
	id 1cO7F1-0006O0-MW
	for gclcip-std-proposals@m.gmane.org; Mon, 02 Jan 2017 19:21:52 +0100
Original-Received: by mail-yw0-f200.google.com with SMTP id t11sf371193794ywe.3
        for <gclcip-std-proposals@m.gmane.org>; Mon, 02 Jan 2017 10:21:55 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=isocpp-org.20150623.gappssmtp.com; s=20150623;
        h=mime-version:in-reply-to:references:from:date:message-id:subject:to
         :x-original-sender:x-original-authentication-results:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=BD9RBLJR8Y7W60xRxdw6EE0UVUnpzUNr1DcDoOhNbnE=;
        b=sfxaK/hg09yaV6CFxi3/y82o2qHpszfThqB1PnJIwFbQmS2NGigi0QGhSoMpOZgiRF
         9KkIAR2CxLZ98dWgj43sKOr1O6Ukzh8xsBvx/rxTWDifg9s9uDPvjo0+I8ghAdd9mPbD
         0u7U1aQfSeB65/oe0iuqoZHKHRggSBhMWUq20nu5RaazKeTOW5UIeNTppqc+xlVrcLFL
         NJ2qaZ1VOPKjWkIbgO03ILSYkty8no0/hf0Gbl+l/HfaT9VtwbQxGghdlS1zOlFsTxGj
         YScMEosvgLdFRtBdczgE7Q4NP8HnXWUpXFOFVdMr33RaKISNA8NAj86Lyy/muL71nSI1
         4lig==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20161025;
        h=x-gm-message-state:mime-version:in-reply-to:references:from:date
         :message-id:subject:to:x-original-sender
         :x-original-authentication-results:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=BD9RBLJR8Y7W60xRxdw6EE0UVUnpzUNr1DcDoOhNbnE=;
        b=r1QR/TptkE8Ms0BWQnsx+b8Fq8sklol2yFxfxQ3b+YF7mXZWPa1KKbkYQgzrMyynu3
         PJpkzQP+p0abfcFl1z/p7Wbmh9zJoNNsP1WYMA9FbtlA0QrZ91gDSlGsZpMEdMiOWe61
         kUsKt3X+7tQMpznMeUOwsbMvwubXfTNlM1SYYgBqlfMo3THqTMXft5KJMoJsb2/6aD19
         9TN4jWUwL3xKCfFZd+FSKwhpQw2obwILNpRgtZuuvrA1GtF3efrONj5Z2R8l1EUrltKy
         2ezSTOHG7x0zN8DuqlQSj5uP8gyWPpku+KKEeUZAQ8fO1HZo1pEvVQAHjzGZCIcuMB3a
         8B0Q==
X-Gm-Message-State: AIkVDXLvny3ogHNE3tOS4Bm9GMBJQYHjM4wTaOZQu2k6aQnhOUppuahTiUlo4nlR3oAw5g==
X-Received: by 10.13.202.83 with SMTP id m80mr16292937ywd.29.1483381315505;
        Mon, 02 Jan 2017 10:21:55 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.157.27.137 with SMTP id z9ls43482299otd.28.gmail; Mon, 02 Jan
 2017 10:21:54 -0800 (PST)
X-Received: by 10.176.84.8 with SMTP id n8mr43887626uaa.29.1483381314632;
        Mon, 02 Jan 2017 10:21:54 -0800 (PST)
Original-Received: from mail-ua0-x235.google.com (mail-ua0-x235.google.com. [2607:f8b0:400c:c08::235])
        by mx.google.com with ESMTPS id y26si12887697uae.155.2017.01.02.10.21.54
        for <std-proposals@isocpp.org>
        (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
        Mon, 02 Jan 2017 10:21:54 -0800 (PST)
Received-SPF: pass (google.com: domain of svalorzen@gmail.com designates 2607:f8b0:400c:c08::235 as permitted sender) client-ip=2607:f8b0:400c:c08::235;
Original-Received: by mail-ua0-x235.google.com with SMTP id 34so266570265uac.1
        for <std-proposals@isocpp.org>; Mon, 02 Jan 2017 10:21:54 -0800 (PST)
X-Received: by 10.176.85.24 with SMTP id t24mr46997654uaa.21.1483381314043;
 Mon, 02 Jan 2017 10:21:54 -0800 (PST)
Original-Received: by 10.31.227.133 with HTTP; Mon, 2 Jan 2017 10:21:53 -0800 (PST)
In-Reply-To: <edb42928-1e58-ee22-79ce-0fedd07247f1@wanadoo.fr>
X-Original-Sender: svalorzen@gmail.com
X-Original-Authentication-Results: mx.google.com;       dkim=pass
 header.i=@gmail.com;       spf=pass (google.com: domain of
 svalorzen@gmail.com designates 2607:f8b0:400c:c08::235 as permitted sender)
 smtp.mailfrom=svalorzen@gmail.com;       dmarc=pass (p=NONE dis=NONE) header.from=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:30156
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/30156>

--f403045dd9604a4623054520a069
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Dear Vicente,

> As in, the compiler knows that the first piece of the class will be the
> same as the original, and every new member is added at the end.
>
> So if we argree that internal conversions are needed from/to the
> underlying type, the new strong type couldn't add any new non-static data
> member :)
>

I'm not sure I agree fully, but in any case the ability to add new
non-static data members is not something I feel strongly about at the
moment. It's something that can be added in a future proposal if there
should arise a need. =3D)

Maybe I'll just remove this from the proposal for the moment.

> Yes, of course. What I mean is, you have created a class which can only
> create exact copies of it. If you need additional changes, it will probab=
ly
> be easier to strong-type the original again and create new trampolines fr=
om
> that. This is what I mean by non-extendable.
>
> Why? I don't understand.
>

It may be that I just have a different idea in my head on how p0109 would
work in practice. I just have a feeling that those strong typedefs could be
hard to work with, but I may just have misunderstood some parts.

> I start to see what you mean. But still, if one could add them, the copy
> would still "contain" an equivalent of the original class at its beginnin=
g.
> It wouldn't be guaranteed reinterpret_cast-able, but the fields would be
> there anyway. The original representation is there - so to me it could
> still be considered a strong-typedef (stretching a bit the definition
> maybe).
>
> Remember that you need conversions from both sides to implement the
> trampolines.
>

Well, in inheritance child classes can be converted to their parents
automatically (even if they don't define a constructor that initializes any
new data they might have). If that can be done I don't see why this would
be impossible for a copied class + a new non-static data member to do the
same thing.

> Well, if only the public interface is available, than adding new methods
> to it is pretty much equivalent with creating non-member functions (since
> those work with public interface). Then you might as well remove the
> ability to add new member functions, since non-members will do just fine
> and there's no need to have them as members.
>
> People like member functions also ;-)
>

Eh, true. But every feature must be justified by a use case! ;D (joking)

> template <typename C>
> class ConvertBack : using C {
>
> public:
>

 Whoops!

> // Strong typedef of double with +,- convertible to double
> struct MyDouble : using ConvertBack<Minus<Plus<Wrap<double>>>> {}
>
> This example is already more complete. Thanks.
>
> --------------------------------------------
>
> ConvertBack will convert to Minus<Plus<Wrap<double>>> :(
>
> Maybe the conversion should be part of Wrap or wrap should provide a
> underlying function as I have in my library.
>
> operator+ returns Plus<Wrap<double>> but we want MyInt or MyDouble :(
>
> See below how you could return the Final class.
>
Not exactly!

I'll try to analyze MyDouble to explain how it works.

Wrap<double> I believe we both understand it. So now let's consider
Plus<Wrap<double>>.

template <typename C>
struct Plus : using C { // changed to struct to avoid public
    Plus operator+(Plus other) { return Plus{t_ + other.t_}; }
};

So it copies the templated class, and adds the operator+ to it. So the
class becomes the equivalent of:

struct Plus { // Equivalent of Plus<Wrap<double>>
    using base_type =3D double;

    Plus(const Plus & other) : t_(other.t_) {}
    explicit Plus(double t) : t_(t) {}

    Plus operator+(Plus other) { return Plus{t_ + other.t_}; }
private:
        double t_;
};

See? Now any mention of Wrap has disappeared, since we copied that.
Wrap<double>, the original class, has been replaced by Plus (since we are
copying). After the minus, the same thing would happen:

struct Minus { // Equivalent of struct Minus<Plus<Wrap<double>>>
    using base_type =3D double;

    Minus(const Minus & other) : t_(other.t_) {}
    explicit Minus(double t) : t_(t) {}

    Minus operator+(Minus other) { return Minus{t_ + other.t_}; }
    Minus operator-(Minus other) { return Minus{t_ - other.t_}; }
private:
        double t_;
};

And finally, the last step:

struct ConvertBack { // Equivalent of struct
ConvertBack<Minus<Plus<Wrap<double>>>>
    using base_type =3D double;

    ConvertBack(const ConvertBack & other) : t_(other.t_) {}
    explicit ConvertBack(double t) : t_(t) {}

    // From Plus originally
    ConvertBack operator+(ConvertBack other) { return ConvertBack{t_ +
other.t_}; }
    // From Minus originally
    ConvertBack operator-(ConvertBack other) { return ConvertBack{t_ -
other.t_}; }
    // From ConvertBack, unchanged, but using the typedef (base_type) made
initially in Wrap<double>
    operator base_type() { return t_; }
private:
        double t_;
};

I hope this makes more sense to you.

template <typename Final, typename C>
> class AFct : using C {
> public:
>     friend Final aFct(Final other) { return Final{aFct(other.t_)}; }
> };


This could be a way, yes.

One option is to simply define a constructor in B which takes A. Otherwise,
> it would be the same case when you create a class with a member which the
> constructor does not initialize. Otherwise one exception could be made fo=
r
> constructors so that they can be redefined in the new class. This probabl=
y
> makes sense and it shoudn't be possible to break something (unless one
> creates a constructor which does not initialize some fields which are
> assumed initialized by the original class.. but then I believe it's a
> reasonable risk).
>
> I suggest you try it and see how it works. Let me know if it is reasonabl=
e.
>

I'll try to work on this a bit then.

Well, friend functions are not members, so if you allow copying them, you
> are allowing copying arbitrary non-member functions (which I approve of).
> The only problem with this is that it is a big change - on top of this
> proposal. Just that.
>
> Not exactly. The compiler can copy the friend functions because it is
> aware of these functions and so it could copy them.
>

This seems reasonable.

However, you still have to specify non-member functions manually, since the
> compiler cannot assume you want them all.
>
> I believe you could let the user copy non-member non-friend function by
> itself.


Yes. However, can you do this process on random non-member functions to
change their parameters to other types? If not, why not? Are you
constrained in doing this only in copied class and with functions
taking/returning the original class, maybe? Why?

I'm not sure what the answers should be.

Well, it is not really transitivity. As in, the C to A transition does not
> need an implicit transition from B. The user is explicitly creating the
> conversion operator. The data in C exists, so it can be copied directly.
> Maybe you mean transitivity in the sense that the compiler needs to
> remember that C is a copy of B in order for it to know that it is also a
> copy of A. In that case I agree.
>
> Yes this is the case. You are requesting the compiler to do the conversio=
n
> transitively.
>

Makes sense. Then forget the idea =3D)

Best,
Eugenio

On Mon, Jan 2, 2017 at 6:48 PM, Vicente J. Botet Escriba <
vicente.botet@wanadoo.fr> wrote:

> Le 02/01/2017 =C3=A0 13:31, Eugenio Bargiacchi a =C3=A9crit :
>
> Dear Vicente,
>
> Eugenio, I believe the use cases we have both in mind are quite different=
,
>> and so we don't reach to understand one to each other.
>
>
> It seems so. I am available to try other forms of communications if you
> want (chat, voice call) if you want. I'm sorry I'm not being as clear as =
I
> want.
>
> No problem. It is my fault also.
>
>
> I have a question. Does you copy class proposal needs to have the
>> definition of the copied class available?
>> If yes, I don't think this could be acceptable.
>> If the declaration is enough, the copied functions would need at least a=
n
>> internal conversion to/from the underlying type, isn't it?
>>
>
> My proposal does not need the definition. Yes, I suppose an internal
> conversion would be needed. The internal conversion would probably work
> similarly to how inheritance works, even if adding non-static members was
> allowed. As in, the compiler knows that the first piece of the class will
> be the same as the original, and every new member is added at the end.
>
> So if we argree that internal conversions are needed from/to the
> underlying type, the new strong type couldn't add any new non-static data
> member :)
>
> B b;
>> b.A::bar(5);
>>
>> Agreed. And the language let me do that even if you find it could be bad
>> practice. I don't see why your copy approach wouldn't let me do that.
>>
>
> In my approach the old function is impossible to hide, so I think that th=
e
> two cases are different.
>
>> If in all these cases your answer is "the program will fail to compile,
>> just copy the class by hand" then I think the feature would be severely
>> limited in what it could actually do.
>>
>> You are probably right, and the copy should copy every thing and give
>> access to everything internally. I need some concrete examples to
>> understand what this possibility will solve.
>>
>
> Well, for example, a library that wanted to create strong typedefs of
> primitive types via wrappers and only expose certain operations, without
> getters/setters ;) I've added some code later to show you how a possible
> implementation using this proposal.
>
>> If I understand correctly, you want to hide the original completely, and
>> just be offered an easy way to bring back some of its interface (via
>> trampolines) to its "wrapper", which would be the strong typedef.
>>
>> I wouldn't say hiding, just don't looking inside the underlying type. I
>> want to provide access to it (when needed) but only as a whole.
>>
>> Possibly adding more public methods only using the public interface,
>> which could be done just the same with non-member methods. The end resul=
t
>> is a class that cannot be extended in any meaningful way using any of th=
e
>> normal C++ facilities, since every juicy bit is hidden.
>>
>> Why it is unusable? The class provide access to everything you want.
>>
>
> Classes don't always come with getters and setters for every private
> field. Especially if the interface they provide is a high level one. It
> happens often in low-level code that you want to interact with the
> underlying bits in very specific ways, but you don't necessarily want to
> give that kind of access to users. So creating a strong typedef of such a
> class while adding a new mode of operation would be impossible, as the co=
py
> won't have access to the underlying implementation.
>
> Another could be when you have to types that you know contain the same
> (private) data, but should expose different public interfaces. Then you
> could first create the class containing the data, and copy it two times,
> each time exposing a different interface (which would need access to the
> private data). Once again, I unfortunately don't have a practical use cas=
e
> at the moment. I just think it could be useful.
>
> Still the code below is a good use-case I think, since it would be needed
> to provide strong typedefs of primitive types.
>
>> Applying strong-typing again to a strong-typed class would be useless as
>> access to internals would be the same,
>>
>> You can strong-type again. I don't see the trouble. E.g; you can have a
>> energy strong-type and have kinetic_energy, potential_energy and
>> heat_energy strong-type of energy.
>> Typing and representation are two different things. Strong types are jus=
t
>> that. Share a representation and have different types.
>>
>
> Yes, of course. What I mean is, you have created a class which can only
> create exact copies of it. If you need additional changes, it will probab=
ly
> be easier to strong-type the original again and create new trampolines fr=
om
> that. This is what I mean by non-extendable.
>
> Why? I don't understand.
>
> aside from possibly adding more data (if needed) in the public attributes=
,
>> since only those are editable. This would also prevent encapsulation of =
new
>> data. If not, it would just mean that the feature wouldn't be used in a
>> composable way.
>>
>> I believe now that strong-type shouldn't add any new non-static data
>> member
>
>
> I start to see what you mean. But still, if one could add them, the copy
> would still "contain" an equivalent of the original class at its beginnin=
g.
> It wouldn't be guaranteed reinterpret_cast-able, but the fields would be
> there anyway. The original representation is there - so to me it could
> still be considered a strong-typedef (stretching a bit the definition
> maybe).
>
> Remember that you need conversions from both sides to implement the
> trampolines.
>
>
> Is there any other reason why you don't like the idea?
>
> No, but it is enough.
>
> A feature that creates a non-extendable object is like a dead-end.
>>
>> I must agree with your last sentence, but I don't think the strong-types
>> I'm suggesting are non-extendable?
>>
>
> Well, if only the public interface is available, than adding new methods
> to it is pretty much equivalent with creating non-member functions (since
> those work with public interface). Then you might as well remove the
> ability to add new member functions, since non-members will do just fine
> and there's no need to have them as members.
>
> People like member functions also ;-)
>
>
> But wrappers can be made in a separate library. Why should they be
>> included in the proposal? As long as the proposal allows them, a library
>> only needs to be made once (and if not needed by someone, not used).
>>
>> We need some probe of concept applied to concrete examples we want to
>> solve. I believe a strong type feature must solve the builtin type case.=
 If
>> your proposal is not a strong type proposal, then forget my comments.
>>
>
> This is how I would practically solve the primitive types problem using m=
y
> proposal:
>
> ------------------------------------------
>
> // library.hpp
>
> template <typename T>
> class Wrap {
>     public:
>         using base_type =3D T;
>
>         Wrap(const Wrap & other) : t_(other.t_) {}
>         explicit Wrap(T t) : t_(t) {}
>
>     private:
>         T t_;
> };
>
> template <typename C>
> class ConvertBack : using C {
>
> public:
>
>     operator base_type() { return t_; }
> };
>
> template <typename C>
> class Plus : using C {
>
> public:
>
>     Plus operator+(Plus other) { return Plus{t_ + other.t_}; }
> };
>
> template <typename C>
> class Minus : using C {
>     Minus operator-(Minus other) { return Minus{t_ - other.t_}; }
> };
>
> template <typename C>
> class Prod : using C {
>     Prod operator+(Prod other) { return Prod{t_ * other.t_}; }
> };
>
> template <typename C>
> class Div : using C {
>     Div operator/(Div other) { return Div{t_ / other.t_}; }
> };
>
> template <typename T>
> using Arithmetic =3D Div<Prod<Minus<Plus<Wrap<T>>>>>;
>
> // .... and so on
>
> // usercode.cpp
>
> #include "library.hpp"
>
> // Strong typedef of int with +,-,/,*
> struct MyInt : using Arithmetic<int> {}
>
> // Strong typedef of double with +,- convertible to double
> struct MyDouble : using ConvertBack<Minus<Plus<Wrap<double>>>> {}
>
> This example is already more complete. Thanks.
>
> --------------------------------------------
>
> ConvertBack will convert to Minus<Plus<Wrap<double>>> :(
>
> Maybe the conversion should be part of Wrap or wrap should provide a
> underlying function as I have in my library.
>
> operator+ returns Plus<Wrap<double>> but we want MyInt or MyDouble :(
>
> See below how you could return the Final class.
>
>
> If there's something missing you'd like to see how I'd do, let me know. O=
f
> course verbosity depends on granularity. If all operations need to be
> manually selected you'll have lots of classes. If the granularity require=
d
> is less each class could add more operators at once.
>
> Note that you need access to privates to be able to do this, so this coul=
d
> be an use-case for that.
>
> I like the idea and yes it needs access to the private data. However if w=
e
> want to be able to provide the conversion to the underlying type, it seem=
s
> that the underlying data  is no more private anymore and should at least =
be
> read. To be fair, I have never created strong types for classes that are
> not builtin types, or that are not copied completely. If the function you
> want to add modifies only part of the underlying type then either the
> underlying type provides already this possibility, or the new type would
> need access to the private part as you propose.
>
> I would need to see how I could adapt my Opaque library with this languag=
e
> feature and see if it could be more simple. I will try with private and
> without access.
>
>
> A problem that is not tackled in this code and that we are also discussin=
g
> is what to do with non-member functions (that could possibly take base_ty=
pe
> as input). That depends on how non-member functions will be handled in th=
e
> proposals. If they can be handled I would actually be happier.
>
> template <typename Final, typename C>
> class AFct : using C {
> public:
>     friend Final aFct(Final other) { return Final{aFct(other.t_)}; }
> };
>
>
> Forcing the user to inherit to add more data adds inheritance, which mean=
s
>> that types are now implicitly convertible (to at least a common base). I
>> don't think this is desirable. I think strong typing should work on its =
own.
>>
>> How then you will be able to construct a B from a A if B adds more
>> non-static data members?
>>
>
> One option is to simply define a constructor in B which takes A.
> Otherwise, it would be the same case when you create a class with a membe=
r
> which the constructor does not initialize. Otherwise one exception could =
be
> made for constructors so that they can be redefined in the new class. Thi=
s
> probably makes sense and it shoudn't be possible to break something (unle=
ss
> one creates a constructor which does not initialize some fields which are
> assumed initialized by the original class.. but then I believe it's a
> reasonable risk).
>
> I suggest you try it and see how it works. Let me know if it is reasonabl=
e.
>
>
> As you want to inherit all the member functions from the underlying class=
,
>> it has a sens to concentrate on member functions. I don't understand why
>> friend functions could not follow the same schema.
>>
>
> Well, friend functions are not members, so if you allow copying them, you
> are allowing copying arbitrary non-member functions (which I approve of).
> The only problem with this is that it is a big change - on top of this
> proposal. Just that.
>
> Not exactly. The compiler can copy the friend functions because it is
> aware of these functions and so it could copy them.
>
>
> void foo(int);
>>
>> void foo(double) : using foo(int);
>>
>> to use an analogous syntax to the one in my proposal. Not sure if this i=
s
>> clearer, let me know.
>>
>> I believe I understand you now but I don't see how this could help.
>>
>
> Well, this would be the way to create the "trampolines" for non-member
> functions. When you copy a class, you specify just once from which class
> you are copying. The compiler can then apply the change to all member
> functions automatically.
>
> However, you still have to specify non-member functions manually, since
> the compiler cannot assume you want them all.
>
> I believe you could let the user copy non-member non-friend function by
> itself.
>
>
> and also to A (since C is a type-copy of a type-copy).
>>
>> The first Opaque proposal contained a implicit subsumption relation that
>> allowed that. I'm all for, but I believe the committee doesn't like
>> transitivity in conversions.
>>
>
> Well, it is not really transitivity. As in, the C to A transition does no=
t
> need an implicit transition from B. The user is explicitly creating the
> conversion operator. The data in C exists, so it can be copied directly.
> Maybe you mean transitivity in the sense that the compiler needs to
> remember that C is a copy of B in order for it to know that it is also a
> copy of A. In that case I agree.
>
> Yes this is the case. You are requesting the compiler to do the conversio=
n
> transitively.
>
>
> Vicente
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/
> isocpp.org/d/topic/std-proposals/gkJUVnL-Fmg/unsubscribe.
> To unsubscribe from this group and all its topics, 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/edb42928-1e58-ee22-
> 79ce-0fedd07247f1%40wanadoo.fr
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/edb42928-1e=
58-ee22-79ce-0fedd07247f1%40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfoot=
er>
> .
>

--=20
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 e=
mail 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/CAHfn%3D%2BsJCyDr4sVhXK-9c9cn0JOdaWt7Fr1ejiCBVT7=
Ab%3DYbew%40mail.gmail.com.

--f403045dd9604a4623054520a069
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Dear Vicente,<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding=
-left:1ex"><span class=3D"gmail-im"><blockquote type=3D"cite"><div dir=3D"l=
tr"><div><div>As in,
            the compiler knows that the first piece of the class will be
            the same as the original, and every new member is added at
            the end.<span class=3D"gmail-m_8086149550023163907gmail-m_-1377=
447551499369339gmail-im"><br>
            </span></div>
        </div>
      </div>
    </blockquote></span>
    So if we argree that internal conversions are needed from/to the
    underlying type, the new strong type couldn&#39;t add any new non-stati=
c
    data member :)<span class=3D"gmail-im"><br></span></blockquote><div><br=
></div><div>I&#39;m not sure I agree fully, but in any case the ability to =
add new non-static data members is not something I feel strongly about at t=
he moment. It&#39;s something that can be added in a future proposal if the=
re should arise a need. =3D)<br><br></div><div>Maybe I&#39;ll just remove t=
his from the proposal for the moment.<br></div><div><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,=
204,204);padding-left:1ex"><span class=3D"gmail-im"><blockquote type=3D"cit=
e"><div dir=3D"ltr"><div><div>Yes, of course. What I mean is, you have crea=
ted a class
            which can only create exact copies of it. If you need
            additional changes, it will probably be easier to
            strong-type the original again and create new trampolines
            from that. This is what I mean by non-extendable.<br>
          </div>
        </div>
      </div>
    </blockquote></span>
    Why? I don&#39;t understand.<span class=3D"gmail-im"><br></span></block=
quote></div><div>=C2=A0<br></div><div>It may be that I just have a differen=
t idea in my head on how <span class=3D"gmail-im">p0109 would work in pract=
ice. I just have a feeling that those strong typedefs could be hard to work=
 with, but I may just have misunderstood some parts.<br></span><span class=
=3D"gmail-im"></span><blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><spa=
n class=3D"gmail-im"><blockquote type=3D"cite"><div dir=3D"ltr"><div><div><=
div>I start to see what you mean. But still, if one could
              add them, the copy would still &quot;contain&quot; an equival=
ent of
              the original class at its beginning. It wouldn&#39;t be
              guaranteed reinterpret_cast-able, but the fields would be
              there anyway. The original representation is there - so to
              me it could still be considered a strong-typedef
              (stretching a bit the definition maybe).<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    Remember that you need conversions from both sides to implement the
    trampolines.<span class=3D"gmail-im"><br></span></blockquote><div><br><=
/div><div>Well, in inheritance child classes can be converted to their pare=
nts automatically (even if they don&#39;t define a constructor that initial=
izes any new data they might have). If that can be done I don&#39;t see why=
 this would be impossible for a copied class + a new non-static data member=
 to do the same thing.<br><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"=
><span class=3D"gmail-im"><blockquote type=3D"cite"><div dir=3D"ltr"><div><=
div><div>Well, if only the public interface is available, than
              adding new methods to it is pretty much equivalent with
              creating non-member functions (since those work with
              public interface). Then you might as well remove the
              ability to add new member functions, since non-members
              will do just fine and there&#39;s no need to have them as
              members.<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    People like member functions also ;-)<span class=3D"gmail-im"><br></spa=
n></blockquote><div><br></div><div>Eh, true. But every feature must be just=
ified by a use case! ;D (joking)<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding=
-left:1ex"><span class=3D"gmail-im"><blockquote type=3D"cite"><div dir=3D"l=
tr"><div><div><div>template &lt;typename C&gt;<br>
              class ConvertBack : using C {<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    public:<span class=3D"gmail-im"><br></span></blockquote><br></div><div>=
=C2=A0Whoops!<br><span class=3D"gmail-im"></span><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204=
,204);padding-left:1ex"><span class=3D"gmail-im"><blockquote type=3D"cite">=
<div dir=3D"ltr"><div><div><div>// Strong typedef of double with +,- conver=
tible to double<br>
              struct MyDouble : using
              ConvertBack&lt;Minus&lt;Plus&lt;Wrap&lt;<wbr>double&gt;&gt;&g=
t;&gt;
              {}<br>
              <br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    This example is already more complete. Thanks.<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <div>------------------------------<wbr>--------------</div>
          </div>
        </div>
      </div>
    </blockquote>
    ConvertBack will convert to
    Minus&lt;Plus&lt;Wrap&lt;double&gt;&gt;&gt; :(<br>
    <br>
    Maybe the conversion should be part of Wrap or wrap should provide a
    underlying function as I have in my library.<br>
    <br>
    operator+ returns Plus&lt;Wrap&lt;double&gt;&gt; but we want MyInt
    or MyDouble :(<br>
    <br>
    See below how you could return the Final class. <br><span class=3D"gmai=
l-im">
    </span></blockquote><span class=3D"gmail-im"><blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra">
        </div></div></blockquote></span>Not exactly!<br><br></div><div>I&#3=
9;ll try to analyze MyDouble to explain how it works.<br><br></div><div>Wra=
p&lt;double&gt; I believe we both understand it. So now let&#39;s consider =
Plus&lt;Wrap&lt;double&gt;&gt;.<br><br>template &lt;typename C&gt;<br>struc=
t Plus : using C { // changed to struct to avoid public<br>=C2=A0=C2=A0=C2=
=A0 Plus operator+(Plus other) { return Plus{t_ + other.t_}; }<br>};<br><br=
></div><div>So it copies the templated class, and adds the operator+ to it.=
 So the class becomes the equivalent of:<br><br></div><div>struct Plus { //=
 Equivalent of Plus&lt;Wrap&lt;double&gt;&gt;<br><span class=3D"gmail-im">=
=C2=A0=C2=A0=C2=A0 using base_type =3D double;<br>
              <br>
              =C2=A0=C2=A0=C2=A0 Plus(const Plus &amp; other) : t_(other.t_=
) {}<br>
              =C2=A0=C2=A0=C2=A0 explicit Plus(double t) : t_(t) {}<br><br>=
</span>=C2=A0=C2=A0=C2=A0 Plus operator+(Plus other) { return Plus{t_ + oth=
er.t_}; }=C2=A0=C2=A0=C2=A0 <br>private:<br></div><div>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 double t_;<br></div><div>};<br><br></div><div>See?=
 Now any mention of Wrap has disappeared, since we copied that. Wrap&lt;dou=
ble&gt;, the original class, has been replaced by Plus (since we are copyin=
g). After the minus, the same thing would happen:<br><br><div>struct Minus =
{ // Equivalent of struct Minus&lt;Plus&lt;Wrap&lt;double&gt;&gt;&gt;<br><s=
pan class=3D"gmail-im">=C2=A0=C2=A0=C2=A0 using base_type =3D double;<br>
              <br>
              =C2=A0=C2=A0=C2=A0 Minus(const Minus &amp; other) : t_(other.=
t_) {}<br>
              =C2=A0=C2=A0=C2=A0 explicit Minus(double t) : t_(t) {}<br><br=
></span>=C2=A0=C2=A0=C2=A0 Minus operator+(Minus other) { return Minus{t_ +=
 other.t_}; }<br><span class=3D"gmail-im">=C2=A0=C2=A0=C2=A0 Minus operator=
-(Minus other) { return Minus{t_ -
              other.t_}; }</span>=C2=A0 <br>private:<br></div><div>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 double t_;<br></div>};<br><br></div><d=
iv>And finally, the last step:<br></div><div><br><div>struct ConvertBack { =
// Equivalent of struct ConvertBack&lt;Minus&lt;Plus&lt;Wrap&lt;double&gt;&=
gt;&gt;&gt;<br><span class=3D"gmail-im">=C2=A0=C2=A0=C2=A0 using base_type =
=3D double;<br>
              <br>
              =C2=A0=C2=A0=C2=A0 </span><span class=3D"gmail-im">ConvertBac=
k(const </span><span class=3D"gmail-im">ConvertBack &amp; other) : t_(other=
..t_) {}<br>
              =C2=A0=C2=A0=C2=A0 explicit </span><span class=3D"gmail-im">C=
onvertBack(double t) : t_(t) {}<br><br></span></div><div><span class=3D"gma=
il-im">=C2=A0=C2=A0=C2=A0 // From Plus originally<br></span></div><div>=C2=
=A0=C2=A0=C2=A0 ConvertBack operator+(ConvertBack other) { return ConvertBa=
ck{t_ + other.t_}; }<br></div><div>=C2=A0=C2=A0=C2=A0 // From Minus origina=
lly<br></div><div><span class=3D"gmail-im">=C2=A0=C2=A0=C2=A0 </span><span =
class=3D"gmail-im">ConvertBack operator-(</span><span class=3D"gmail-im">Co=
nvertBack other) { return </span><span class=3D"gmail-im">ConvertBack{t_ -
              other.t_}; }<br></span></div><div><span class=3D"gmail-im">=
=C2=A0=C2=A0=C2=A0 // From ConvertBack, unchanged, but using the typedef (b=
ase_type) made initially in Wrap&lt;double&gt;<br></span></div><div><span c=
lass=3D"gmail-im">=C2=A0=C2=A0=C2=A0 operator base_type() { return t_; }</s=
pan> <br>private:<br></div><div>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
double t_;<br></div>};<br><br></div><div>I hope this makes more sense to yo=
u.<br><br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">template &lt;ty=
pename Final, typename C&gt;<br>
    class AFct : using C {<br>
    public:<br>
    =C2=A0=C2=A0=C2=A0 friend Final aFct(Final other) { return Final{aFct(o=
ther.t_)}; }<br>
    };
    </blockquote><div><br></div><div>This could be a way, yes.<br><br><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:=
1px solid rgb(204,204,204);padding-left:1ex"><span class=3D"gmail-im"><bloc=
kquote type=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_extra">One option=
 is to simply define a
          constructor in B which takes A. Otherwise, it would be the
          same case when you create a class with a member which the
          constructor does not initialize. Otherwise one exception could
          be made for constructors so that they can be redefined in the
          new class. This probably makes sense and it shoudn&#39;t be
          possible to break something (unless one creates a constructor
          which does not initialize some fields which are assumed
          initialized by the original class.. but then I believe it&#39;s a
          reasonable risk).<br>
        </div>
      </div>
    </blockquote></span>
    I suggest you try it and see how it works. Let me know if it is
    reasonable.<span class=3D"gmail-im"><br></span></blockquote><div><br></=
div><div>I&#39;ll try to work on this a bit then.<br><br><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rg=
b(204,204,204);padding-left:1ex"><span class=3D"gmail-im"><blockquote type=
=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_extra"><div>Well, friend fun=
ctions are not members, so if you allow
            copying them, you are allowing copying arbitrary non-member
            functions (which I approve of). The only problem with this
            is that it is a big change - on top of this proposal. Just
            that.<br>
          </div>
        </div>
      </div>
    </blockquote></span>
    Not exactly. The compiler can copy the friend functions because it
    is aware of these functions and so it could copy them.<span class=3D"gm=
ail-im"><br></span></blockquote><div><br></div><div>This seems reasonable.<=
br><br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;=
border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=3D"gma=
il-im"><blockquote type=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_extra=
">However, you still have to specify non-member functions
          manually, since the compiler cannot assume you want them all.<br>
        </div>
      </div>
    </blockquote></span>
    I believe you could let the user copy non-member non-friend function
    by itself.</blockquote><div><br></div><div>Yes. However, can you do thi=
s process on random non-member functions to change their parameters to othe=
r types? If not, why not? Are you constrained in doing this only in copied =
class and with functions taking/returning the original class, maybe? Why?<b=
r><br></div><div>I&#39;m not sure what the answers should be.<br><br><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1=
px solid rgb(204,204,204);padding-left:1ex"><span class=3D"gmail-im"><block=
quote type=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_extra">Well, it is=
 not really transitivity. As
          in, the C to A transition does not need an implicit transition
          from B. The user is explicitly creating the conversion
          operator. The data in C exists, so it can be copied directly.
          Maybe you mean transitivity in the sense that the compiler
          needs to remember that C is a copy of B in order for it to
          know that it is also a copy of A. In that case I agree.<br>
        </div>
      </div>
    </blockquote></span>
    Yes this is the case. You are requesting the compiler to do the
    conversion transitively.<br></blockquote><div><br></div><div>Makes sens=
e. Then forget the idea =3D)<br><br></div><div>Best,<br></div><div>Eugenio<=
br></div></div></div> </div></div></div></div></div></div><div class=3D"gma=
il_extra"><br><div class=3D"gmail_quote">On Mon, Jan 2, 2017 at 6:48 PM, Vi=
cente J. Botet Escriba <span dir=3D"ltr">&lt;<a href=3D"mailto:vicente.bote=
t@wanadoo.fr" target=3D"_blank">vicente.botet@wanadoo.fr</a>&gt;</span> wro=
te:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex">
 =20
   =20
 =20
  <div bgcolor=3D"#FFFFFF" text=3D"#000000"><span class=3D"">
    <div class=3D"m_8086149550023163907moz-cite-prefix">Le 02/01/2017 =C3=
=A0 13:31, Eugenio
      Bargiacchi a =C3=A9crit=C2=A0:<br>
    </div>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">Dear Vicente,<br>
        <br>
        <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;border-left:1px solid rgb(204,204,204);padding-left:1ex">Eugenio,
          I believe the use cases we have both in mind are quite
          different, and so we don&#39;t reach to understand one to each
          other.</blockquote>
        <div><br>
        </div>
        <div>It seems so. I am available to try other forms of
          communications if you want (chat, voice call) if you want. I&#39;=
m
          sorry I&#39;m not being as clear as I want.<br>
        </div>
      </div>
    </blockquote></span>
    No problem. It is my fault also.<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div><br>
          <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I have a questi=
on. Does
            you copy class proposal needs to have the definition of the
            copied class available?<br>
            If yes, I don&#39;t think this could be acceptable.<br>
            If the declaration is enough, the copied functions would
            need at least an internal conversion to/from the underlying
            type, isn&#39;t it?<span class=3D"m_8086149550023163907gmail-m_=
-1377447551499369339gmail-im"><br>
            </span></blockquote>
          <div><br>
          </div>
          <div>My proposal does not need the definition. Yes, I suppose
            an internal conversion would be needed. The internal
            conversion would probably work similarly to how inheritance
            works, even if adding non-static members was allowed. As in,
            the compiler knows that the first piece of the class will be
            the same as the original, and every new member is added at
            the end.<span class=3D"m_8086149550023163907gmail-m_-1377447551=
499369339gmail-im"><br>
            </span></div>
        </div>
      </div>
    </blockquote></span>
    So if we argree that internal conversions are needed from/to the
    underlying type, the new strong type couldn&#39;t add any new non-stati=
c
    data member :)<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <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"><span class=
=3D"m_8086149550023163907gmail-m_-1377447551499369339gmail-im">
                <blockquote type=3D"cite">
                  <div dir=3D"ltr">
                    <div>
                      <div>B b;<br>
                        b.A::bar(5);<br>
                        <br>
                      </div>
                    </div>
                  </div>
                </blockquote>
              </span> Agreed. And the language let me do that even if
              you find it could be bad practice. I don&#39;t see why your
              copy approach wouldn&#39;t let me do that.<span class=3D"m_80=
86149550023163907gmail-m_-1377447551499369339gmail-im"><br>
              </span></blockquote>
            <div><br>
            </div>
            <div>In my approach the old function is impossible to hide,
              so I think that the two cases are different.<br>
              <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=
=3D"m_8086149550023163907gmail-im">
                  <blockquote type=3D"cite">
                    <div dir=3D"ltr">
                      <div>
                        <div>
                          <div>If in all these cases your answer is &quot;t=
he
                            program will fail to compile, just copy the
                            class by hand&quot; then I think the feature
                            would be severely limited in what it could
                            actually do.<br>
                          </div>
                        </div>
                      </div>
                    </div>
                  </blockquote>
                </span> You are probably right, and the copy should copy
                every thing and give access to everything internally. I
                need some concrete examples to understand what this
                possibility will solve.<span class=3D"m_8086149550023163907=
gmail-im"><br>
                </span></blockquote>
              <div><br>
              </div>
              <div>Well, for example, a library that wanted to create
                strong typedefs of primitive types via wrappers and only
                expose certain operations, without getters/setters ;)
                I&#39;ve added some code later to show you how a possible
                implementation using this proposal.<br>
                <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span cla=
ss=3D"m_8086149550023163907gmail-im">
                    <blockquote type=3D"cite">
                      <div dir=3D"ltr">
                        <div>
                          <div>
                            <div> If I understand correctly, you want to
                              hide the original completely, and just be
                              offered an easy way to bring back some of
                              its interface (via trampolines) to its
                              &quot;wrapper&quot;, which would be the stron=
g
                              typedef. </div>
                          </div>
                        </div>
                      </div>
                    </blockquote>
                  </span> I wouldn&#39;t say hiding, just don&#39;t looking
                  inside the underlying type. I want to provide access
                  to it (when needed) but only as a whole.<span class=3D"m_=
8086149550023163907gmail-im"><br>
                    <blockquote type=3D"cite">
                      <div dir=3D"ltr">
                        <div>
                          <div>
                            <div>Possibly adding more public methods
                              only using the public interface, which
                              could be done just the same with
                              non-member methods. The end result is a
                              class that cannot be extended in any
                              meaningful way using any of the normal C++
                              facilities, since every juicy bit is
                              hidden. </div>
                          </div>
                        </div>
                      </div>
                    </blockquote>
                  </span> Why it is unusable? The class provide access
                  to everything you want.<span class=3D"m_80861495500231639=
07gmail-im"><br>
                  </span></blockquote>
                <div><br>
                </div>
                <div>Classes don&#39;t always come with getters and setters
                  for every private field. Especially if the interface
                  they provide is a high level one. It happens often in
                  low-level code that you want to interact with the
                  underlying bits in very specific ways, but you don&#39;t
                  necessarily want to give that kind of access to users.
                  So creating a strong typedef of such a class while
                  adding a new mode of operation would be impossible, as
                  the copy won&#39;t have access to the underlying
                  implementation.<br>
                  <br>
                  Another could be when you have to types that you know
                  contain the same (private) data, but should expose
                  different public interfaces. Then you could first
                  create the class containing the data, and copy it two
                  times, each time exposing a different interface (which
                  would need access to the private data). Once again, I
                  unfortunately don&#39;t have a practical use case at the
                  moment. I just think it could be useful.<br>
                  <br>
                </div>
                <div>Still the code below is a good use-case I think,
                  since it would be needed to provide strong typedefs of
                  primitive types.<br>
                </div>
                <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"><span c=
lass=3D"m_8086149550023163907gmail-im">
                      <blockquote type=3D"cite">
                        <div dir=3D"ltr">
                          <div>
                            <div>
                              <div>Applying strong-typing again to a
                                strong-typed class would be useless as
                                access to internals would be the same, </di=
v>
                            </div>
                          </div>
                        </div>
                      </blockquote>
                    </span> You can strong-type again. I don&#39;t see the
                    trouble. E.g; you can have a energy strong-type and
                    have kinetic_energy, potential_energy and=C2=A0
                    heat_energy strong-type of energy.<br>
                    Typing and representation are two different things.
                    Strong types are just that. Share a representation
                    and have different types.<span class=3D"m_8086149550023=
163907gmail-im"><br>
                    </span></blockquote>
                </div>
              </div>
            </div>
            <br>
          </div>
          <div>Yes, of course. What I mean is, you have created a class
            which can only create exact copies of it. If you need
            additional changes, it will probably be easier to
            strong-type the original again and create new trampolines
            from that. This is what I mean by non-extendable.<br>
          </div>
        </div>
      </div>
    </blockquote></span>
    Why? I don&#39;t understand.<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <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"><span class=
=3D"m_8086149550023163907gmail-im">
                <blockquote type=3D"cite">
                  <div dir=3D"ltr">
                    <div>
                      <div>
                        <div>aside from possibly adding more data (if
                          needed) in the public attributes, since only
                          those are editable. This would also prevent
                          encapsulation of new data. If not, it would
                          just mean that the feature wouldn&#39;t be used i=
n
                          a composable way.<br>
                        </div>
                      </div>
                    </div>
                  </div>
                </blockquote>
              </span> I believe now that strong-type shouldn&#39;t add any
              new non-static data member</blockquote>
            <div><br>
            </div>
            <div>I start to see what you mean. But still, if one could
              add them, the copy would still &quot;contain&quot; an equival=
ent of
              the original class at its beginning. It wouldn&#39;t be
              guaranteed reinterpret_cast-able, but the fields would be
              there anyway. The original representation is there - so to
              me it could still be considered a strong-typedef
              (stretching a bit the definition maybe).<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    Remember that you need conversions from both sides to implement the
    trampolines.<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <div><br>
            </div>
            <div>Is there any other reason why you don&#39;t like the idea?=
<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    No, but it is enough. <br><span class=3D"">
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <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"><span class=
=3D"m_8086149550023163907gmail-im">
                  <blockquote type=3D"cite">
                    <div dir=3D"ltr">
                      <div>
                        <div>
                          <div>A feature that creates a non-extendable
                            object is like a dead-end.<br>
                          </div>
                        </div>
                      </div>
                    </div>
                  </blockquote>
                </span> I must agree with your last sentence, but I
                don&#39;t think the strong-types I&#39;m suggesting are
                non-extendable?<span class=3D"m_8086149550023163907gmail-im=
"></span> <br>
              </blockquote>
            </div>
            <div><br>
            </div>
            <div>Well, if only the public interface is available, than
              adding new methods to it is pretty much equivalent with
              creating non-member functions (since those work with
              public interface). Then you might as well remove the
              ability to add new member functions, since non-members
              will do just fine and there&#39;s no need to have them as
              members.<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    People like member functions also ;-)<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <div><br>
              <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=
=3D"m_8086149550023163907gmail-im">
                  <blockquote type=3D"cite">
                    <div dir=3D"ltr">
                      <div>
                        <div>
                          <div>But wrappers can be made in a separate
                            library. Why should they be included in the
                            proposal? As long as the proposal allows
                            them, a library only needs to be made once
                            (and if not needed by someone, not used).<br>
                          </div>
                        </div>
                      </div>
                    </div>
                  </blockquote>
                </span> We need some probe of concept applied to
                concrete examples we want to solve. I believe a strong
                type feature must solve the builtin type case. If your
                proposal is not a strong type proposal, then forget my
                comments.<span class=3D"m_8086149550023163907gmail-im"><br>
                </span></blockquote>
            </div>
            <div><span class=3D"m_8086149550023163907gmail-im"></span><br>
            </div>
            <div>This is how I would practically solve the primitive
              types problem using my proposal:<br>
              <br>
              ------------------------------<wbr>------------<br>
              <br>
              // library.hpp<br>
              <br>
              template &lt;typename T&gt;<br>
              class Wrap {<br>
              =C2=A0=C2=A0=C2=A0 public:<br>
              =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using base_type =
=3D T;<br>
              <br>
              =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Wrap(const Wrap &a=
mp; other) : t_(other.t_) {}<br>
              =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 explicit Wrap(T t)=
 : t_(t) {}<br>
              =C2=A0=C2=A0=C2=A0 <br>
              =C2=A0=C2=A0=C2=A0 private:<br>
              =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 T t_;<br>
              };<br>
              <br>
              template &lt;typename C&gt;<br>
              class ConvertBack : using C {<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    public:<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <div>=C2=A0=C2=A0=C2=A0 operator base_type() { return t_; }<br>
              };<br>
              <br>
              template &lt;typename C&gt;<br>
              class Plus : using C {<br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    public:<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <div>=C2=A0=C2=A0=C2=A0 Plus operator+(Plus other) { return Plu=
s{t_ +
              other.t_}; }<br>
              };<br>
              <br>
              template &lt;typename C&gt;<br>
              class Minus : using C {<br>
              =C2=A0=C2=A0=C2=A0 Minus operator-(Minus other) { return Minu=
s{t_ -
              other.t_}; }<br>
              };<br>
              <br>
              template &lt;typename C&gt;<br>
              class Prod : using C {<br>
              =C2=A0=C2=A0=C2=A0 Prod operator+(Prod other) { return Prod{t=
_ *
              other.t_}; }<br>
              };<br>
              <br>
              template &lt;typename C&gt;<br>
              class Div : using C {<br>
              =C2=A0=C2=A0=C2=A0 Div operator/(Div other) { return Div{t_ /=
 other.t_};
              }<br>
              };<br>
              <br>
              template &lt;typename T&gt;<br>
              using Arithmetic =3D
              Div&lt;Prod&lt;Minus&lt;Plus&lt;Wrap&lt;T&gt;&gt;&gt;&gt;<wbr=
>&gt;;<br>
              <br>
              // .... and so on<br>
              <br>
              // usercode.cpp<br>
              <br>
              #include &quot;library.hpp&quot;<br>
              <br>
              // Strong typedef of int with +,-,/,*<br>
              struct MyInt : using Arithmetic&lt;int&gt; {}<br>
              <br>
              // Strong typedef of double with +,- convertible to double<br=
>
              struct MyDouble : using
              ConvertBack&lt;Minus&lt;Plus&lt;Wrap&lt;<wbr>double&gt;&gt;&g=
t;&gt;
              {}<br>
              <br>
            </div>
          </div>
        </div>
      </div>
    </blockquote></span>
    This example is already more complete. Thanks.<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div>
          <div>
            <div>------------------------------<wbr>--------------</div>
          </div>
        </div>
      </div>
    </blockquote>
    ConvertBack will convert to
    Minus&lt;Plus&lt;Wrap&lt;double&gt;&gt;&gt; :(<br>
    <br>
    Maybe the conversion should be part of Wrap or wrap should provide a
    underlying function as I have in my library.<br>
    <br>
    operator+ returns Plus&lt;Wrap&lt;double&gt;&gt; but we want MyInt
    or MyDouble :(<br>
    <br>
    See below how you could return the Final class. <br><span class=3D"">
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra"><br>
        </div>
        <div class=3D"gmail_extra">If there&#39;s something missing you&#39=
;d like
          to see how I&#39;d do, let me know. Of course verbosity depends o=
n
          granularity. If all operations need to be manually selected
          you&#39;ll have lots of classes. If the granularity required is
          less each class could add more operators at once.<br>
          <br>
        </div>
        <div class=3D"gmail_extra">Note that you need access to privates
          to be able to do this, so this could be an use-case for that.<br>
        </div>
      </div>
    </blockquote></span>
    I like the idea and yes it needs access to the private data. However
    if we want to be able to provide the conversion to the underlying
    type, it seems that the underlying data=C2=A0 is no more private anymor=
e
    and should at least be read. To be fair, I have never created strong
    types for classes that are not builtin types, or that are not copied
    completely. If the function you want to add modifies only part of
    the underlying type then either the underlying type provides already
    this possibility, or the new type would need access to the private
    part as you propose.<br>
    <br>
    I would need to see how I could adapt my Opaque library with this
    language feature and see if it could be more simple. I will try with
    private and without access.<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra"><br>
        </div>
        <div class=3D"gmail_extra">A problem that is not tackled in this
          code and that we are also discussing is what to do with
          non-member functions (that could possibly take base_type as
          input). That depends on how non-member functions will be
          handled in the proposals. If they can be handled I would
          actually be happier.<br>
        </div>
      </div>
    </blockquote></span>
    template &lt;typename Final, typename C&gt;<br>
    class AFct : using C {<br>
    public:<br>
    =C2=A0=C2=A0=C2=A0 friend Final aFct(Final other) { return Final{aFct(o=
ther.t_)}; }<br>
    };
    <span class=3D""><blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra"><br>
          <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=3D"=
m_8086149550023163907gmail-im">
              <blockquote type=3D"cite">
                <div dir=3D"ltr">
                  <div>
                    <div>
                      <div>
                        <div>Forcing the user to inherit to add more
                          data adds inheritance, which means that types
                          are now implicitly convertible (to at least a
                          common base). I don&#39;t think this is desirable=
..
                          I think strong typing should work on its own.<br>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </blockquote>
            </span> How then you will be able to construct a B from a A
            if B adds more non-static data members?<span class=3D"m_8086149=
550023163907gmail-im"><br>
            </span></blockquote>
        </div>
        <div class=3D"gmail_extra"><br>
        </div>
        <div class=3D"gmail_extra">One option is to simply define a
          constructor in B which takes A. Otherwise, it would be the
          same case when you create a class with a member which the
          constructor does not initialize. Otherwise one exception could
          be made for constructors so that they can be redefined in the
          new class. This probably makes sense and it shoudn&#39;t be
          possible to break something (unless one creates a constructor
          which does not initialize some fields which are assumed
          initialized by the original class.. but then I believe it&#39;s a
          reasonable risk).<br>
        </div>
      </div>
    </blockquote></span>
    I suggest you try it and see how it works. Let me know if it is
    reasonable.<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra"><br>
          <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">As you want to =
inherit
            all the member functions from the underlying class, it has a
            sens to concentrate on member functions. I don&#39;t understand
            why friend functions could not follow the same schema.<span cla=
ss=3D"m_8086149550023163907gmail-im"><br>
            </span></blockquote>
          <div><br>
          </div>
          <div>Well, friend functions are not members, so if you allow
            copying them, you are allowing copying arbitrary non-member
            functions (which I approve of). The only problem with this
            is that it is a big change - on top of this proposal. Just
            that.<br>
          </div>
        </div>
      </div>
    </blockquote></span>
    Not exactly. The compiler can copy the friend functions because it
    is aware of these functions and so it could copy them.<span class=3D"">=
<br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra">
          <div><span class=3D"m_8086149550023163907gmail-im"><br>
            </span><span class=3D"m_8086149550023163907gmail-im"></span>
            <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=
=3D"m_8086149550023163907gmail-im">
                <blockquote type=3D"cite">
                  <div dir=3D"ltr">
                    <div>
                      <div>
                        <div>
                          <div>
                            <div>
                              <div>void foo(int);<br>
                                <br>
                              </div>
                              <div>void foo(double) : using foo(int);<br>
                                <br>
                              </div>
                              <div>to use an analogous syntax to the one
                                in my proposal. Not sure if this is
                                clearer, let me know.<br>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </blockquote>
              </span> I believe I understand you now but I don&#39;t see ho=
w
              this could help.<span class=3D"m_8086149550023163907gmail-im"=
><br>
              </span></blockquote>
            =C2=A0</div>
        </div>
        <div class=3D"gmail_extra">Well, this would be the way to create
          the &quot;trampolines&quot; for non-member functions. When you co=
py a
          class, you specify just once from which class you are copying.
          The compiler can then apply the change to all member functions
          automatically.<br>
          <br>
          However, you still have to specify non-member functions
          manually, since the compiler cannot assume you want them all.<br>
        </div>
      </div>
    </blockquote></span>
    I believe you could let the user copy non-member non-friend function
    by itself.<span class=3D""><br>
    <blockquote type=3D"cite">
      <div dir=3D"ltr">
        <div class=3D"gmail_extra"><span class=3D"m_8086149550023163907gmai=
l-im"><br>
          </span>
          <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=3D"=
m_8086149550023163907gmail-im">
              <blockquote type=3D"cite">
                <div dir=3D"ltr">
                  <div>
                    <div>
                      <div>
                        <div>
                          <div>
                            <div>
                              <div>and also to A (since C is a type-copy
                                of a type-copy).<br>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </blockquote>
            </span> The first Opaque proposal contained a implicit
            subsumption relation that allowed that. I&#39;m all for, but I
            believe the committee doesn&#39;t like transitivity in
            conversions.<span class=3D"m_8086149550023163907gmail-im"><br>
            </span></blockquote>
          <br>
        </div>
        <div class=3D"gmail_extra">Well, it is not really transitivity. As
          in, the C to A transition does not need an implicit transition
          from B. The user is explicitly creating the conversion
          operator. The data in C exists, so it can be copied directly.
          Maybe you mean transitivity in the sense that the compiler
          needs to remember that C is a copy of B in order for it to
          know that it is also a copy of A. In that case I agree.<br>
        </div>
      </div>
    </blockquote></span>
    Yes this is the case. You are requesting the compiler to do the
    conversion transitively.<br>
    <br>
    <br>
    Vicente
  </div><span class=3D"">


<p></p>

-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/gkJUVnL-Fmg/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/<wbr>isocpp.org/d/topic/std-<wbr>proposals/g=
kJUVnL-Fmg/<wbr>unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/edb42928-1e58-ee22-79ce-0fedd07247f1%=
40wanadoo.fr?utm_medium=3Demail&amp;utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/edb4=
2928-1e58-ee22-<wbr>79ce-0fedd07247f1%40wanadoo.fr</a><wbr>.<br>
</blockquote></div><br></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/CAHfn%3D%2BsJCyDr4sVhXK-9c9cn0JOdaWt7=
Fr1ejiCBVT7Ab%3DYbew%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHfn%3D%2B=
sJCyDr4sVhXK-9c9cn0JOdaWt7Fr1ejiCBVT7Ab%3DYbew%40mail.gmail.com</a>.<br />

--f403045dd9604a4623054520a069--

.
