220 2754 <CAOHCbitBc-bgxOgMZwDqKeK_LAm8NV3HjEnZwA=qeKkYC0KXkw@mail.gmail.com> article
Path: news.gmane.org!not-for-mail
From: Tony V E <tvaneerd@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: optional references -- take 2
Date: Wed, 6 Feb 2013 12:00:01 -0500
Lines: 444
Approved: news@gmane.org
Message-ID: <CAOHCbitBc-bgxOgMZwDqKeK_LAm8NV3HjEnZwA=qeKkYC0KXkw@mail.gmail.com>
References: <8d57e9e9-e4cc-441c-abeb-e6526531fad5@isocpp.org>
	<CAOHCbiuw0zezce9kcXVsEcE=mPmp=93zQHSRMzUcNw6u3TCsBQ@mail.gmail.com>
	<ca43f129-cd55-43d3-89fc-1e4402af0e9f@isocpp.org>
	<CAOHCbivkX3wbRi6dTAcpZ1EmbpOjx_h6VkCqN8KHT0mZ_UWUXQ@mail.gmail.com>
	<13f19963-066b-4170-a6f2-eb90bed29be1@isocpp.org>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
X-Trace: ger.gmane.org 1360170003 31419 80.91.229.3 (6 Feb 2013 17:00:03 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Wed, 6 Feb 2013 17:00:03 +0000 (UTC)
To: std-proposals@isocpp.org
Original-X-From: std-proposals+bncBCUZ5QWKNQIJFGGKRACRUBHQMH6KS@isocpp.org Wed Feb 06 18:00:24 2013
Return-path: <std-proposals+bncBCUZ5QWKNQIJFGGKRACRUBHQMH6KS@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-qa0-f70.google.com ([209.85.216.70])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBCUZ5QWKNQIJFGGKRACRUBHQMH6KS@isocpp.org>)
	id 1U38MA-0006BH-ET
	for gclcip-std-proposals@m.gmane.org; Wed, 06 Feb 2013 18:00:22 +0100
Original-Received: by mail-qa0-f70.google.com with SMTP id bs12sf2417606qab.9
        for <gclcip-std-proposals@m.gmane.org>; Wed, 06 Feb 2013 09:00:03 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=x-received:x-beenthere:x-received:x-received:received-spf
         :mime-version:x-received:in-reply-to:references:date:message-id
         :subject:from:to:x-original-sender:x-original-authentication-results
         :reply-to:precedence:mailing-list:list-id:x-google-group-id
         :list-post:list-help:list-archive:list-subscribe:list-unsubscribe
         :content-type:content-transfer-encoding;
        bh=UYn+OX76opmLTCh1Yk3Cl5/yHkCGlT/M9QzcdVxuQP4=;
        b=fh0g9CYNKRrcScwBi5ES48uw0zkKMU3GTgWculmaI0dYJeZXIBO93TFlJZR0CkVupy
         ebBYjO83tgSH85JLqJ7on463jjXJIsjvvLNILei9c7fUpq5JUHgZK9Y/PxAnP4EaoMLr
         oOMpZbyiWVfFO0kU8GRf5bcr/74aWZsQsO4vA9AODtl52KfR7rLu7bNNk0jnQsiM4BmZ
         luHZunifyB4ulvCQ/VdzV7oOD8SVE8rMqYgiyT9oSaimXXPvURwbiW2rPZ/3/ea1SdEE
         f053EHS+K+l4D2eHbbr8lAa 
X-Received: by 10.224.178.207 with SMTP id bn15mr1710694qab.1.1360170002878;
        Wed, 06 Feb 2013 09:00:02 -0800 (PST)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.49.119.162 with SMTP id kv2ls448246qeb.86.gmail; Wed, 06 Feb
 2013 09:00:02 -0800 (PST)
X-Received: by 10.229.177.14 with SMTP id bg14mr5158261qcb.51.1360170002393;
        Wed, 06 Feb 2013 09:00:02 -0800 (PST)
X-Received: by 10.229.177.14 with SMTP id bg14mr5158260qcb.51.1360170002358;
        Wed, 06 Feb 2013 09:00:02 -0800 (PST)
Original-Received: from mail-qc0-f181.google.com (mail-qc0-f181.google.com [209.85.216.181])
        by mx.google.com with ESMTPS id p13si6358261qct.137.2013.02.06.09.00.02
        (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
        Wed, 06 Feb 2013 09:00:02 -0800 (PST)
Received-SPF: pass (google.com: domain of tvaneerd@gmail.com designates 209.85.216.181 as permitted sender) client-ip=209.85.216.181;
Original-Received: by mail-qc0-f181.google.com with SMTP id a22so615078qcs.12
        for <std-proposals@isocpp.org>; Wed, 06 Feb 2013 09:00:02 -0800 (PST)
X-Received: by 10.49.64.234 with SMTP id r10mr24756270qes.24.1360170001981;
 Wed, 06 Feb 2013 09:00:01 -0800 (PST)
Original-Received: by 10.49.87.168 with HTTP; Wed, 6 Feb 2013 09:00:01 -0800 (PST)
In-Reply-To: <13f19963-066b-4170-a6f2-eb90bed29be1@isocpp.org>
X-Original-Sender: tvaneerd@gmail.com
X-Original-Authentication-Results: mx.google.com;       spf=pass (google.com:
 domain of tvaneerd@gmail.com designates 209.85.216.181 as permitted sender)
 smtp.mail=tvaneerd@gmail.com;       dkim=pass header.i=@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: <http://groups.google.com/a/isocpp.org/group/std-proposals/post?hl=en>,
 <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?hl=en&topic=25838>,
 <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe?hl=en>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe?hl=en>,
 <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:2754
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/2754>

On Wed, Feb 6, 2013 at 5:08 AM, Andrzej Krzemie=F1ski <akrzemi1@gmail.com> =
wrote:
>
>
> W dniu wtorek, 5 lutego 2013 23:39:16 UTC+1 u=BFytkownik Tony V E napisa=
=B3:
>>
>> On Tue, Feb 5, 2013 at 3:02 PM, Andrzej Krzemie=F1ski <akrz...@gmail.com=
>
>> wrote:
>> >>
>> >> Is optional<T&> a RegularType?
>> >
>> >
>> > I am not sure how to answer the question. Different people have slight=
ly
>> > different expectations of a regular type.
>>
>> That's why I cc'ed Sean Parent :-)
>>
>> Let's go with Stepanov, via http://www.stepanovpapers.com/DeSt98.pdf
>> and Elements of Programming (www.elementsofprogramming.com)
>>
>> > optional<T&> has:
>> >
>> > default ctor
>> > destructor
>> > copy/move constructor (shallow)
>> > copy/move assignment (shallow)
>> > equality comparison (deep, provided that T is comparable)
>> > it is not swappable yet, but I intend to add a shallow swap
>> >
>> > I am not not sure what semantic requirements a RegularType requires.
>>
>> To summarize Stepanov, mainly the semantics of int w.r.t. copy,
>> assignment, and equality:
>>
>> T b =3D ...<any value of T>;
>> T a =3D b;
>> assert(a =3D=3D b);
>
>
> This holds, but -- so to say -- only by chance
>>
>>
>> T c =3D b;
>> change(a);
>> assert(c =3D=3D b && a !=3D b);
>
>
> Well, this one is tricky. Given this criterion, would you say a raw point=
er
> satisfies it? IOW, does change(a) also applies to changing the referred t=
o
> (or pointed to) object?
>

I knew I should have written change(a) as:
a =3D some_other_value;

:-)

(I started writing "Given T val1, val2 with val1 !=3D val2..." but it
was getting even longer.  Stepanov used 'zap(a)', I thought
"change(a)" was at least an improvement.)

Pointers are value-types, RegularTypes - their value is an address.
We tend to *use* them for reference semantics on the pointee, but they
are actually Regular as a type.

> int i =3D 0;
>
> int j =3D 1;
> optional<int&> oi =3D i;
> optional<int&> oj =3D oi;
>
> assert (oi =3D=3D oj); // holds
>
> optional<int&> ok =3D oi;
> oi =3D {j}; // this is the change(a)
>
> assert (ok =3D=3D oj); // holds
> assert (oj !=3D oi) // holds
>
> j =3D 0;
> assert (oj !=3D oi) // DOES NOT HOLD
>
> And this is what I call an "asynchronous change". The value of 'j' should=
n't
> affect the axioms.
>

Right, but the value of j does affect the axioms, because =3D=3D isn't
working on the same "plane" as =3D.
Somewhat understandable, but :-(


>>
>> oh, and since I happen to always use construction above, I should
>> mention assignment and construction yield the same results, ie:
>>
>> T a; a =3D b;  <=3D=3D> T a =3D b;
>
>
> This holds

It holds for optional=3Doptional, but maybe not mixed-assignment, if
that is allowed.  (I know you are _not_ talking about mixed-assign
here, but I wanted to point it out, maybe just to myself even).

And doesn't hold when T is int &.  Another reason why int & is not Regular:

int & a =3D some_int; a =3D b;  <=3D!=3D>  int & a =3D b;

I'll come back to that later.

>
>>
>>
>> (he also requires less-than, but we can ignore that here)
>
>
> operator< also works, with similar problems as operator=3D=3D
>
>>
>>
>> > The
>> > value compared by operator=3D=3D is not under control of the optional
>> > object: it
>> > can change "asynchronously".
>>
>> Let's limit our discussion to optionals over Ts where T is Regular.  I
>> agree there is not much we can do when T is not Regular.
>> So in general, optional<T> is Regular if T is Regular, I think. (?)
>
>
> The problem I (clumsily) describe also works for Regular T's:
>
> int i =3D 0;
>
> int j =3D 0;
> optional<int&> oi =3D i;
> optional<int&> oj =3D j;
>
> assert (oi =3D=3D oj);

but that assert is by coincidence, nothing more.

> i =3D 9; // the "asynchronous change"
> assert (oi !=3D oj);
>

yes "spooky action at a distance" - why I don't like: raw pointers,
shared pointers, java, reference semantics, global variables

>>
>>
>> > Also the copy/move operations are not
>> > compatible with operator=3D=3D: the former are shallow, the latter is =
deep.
>> >
>>
>> That the part I'm wondering about.  I guess the key thing is that even
>> though T is regular, T & isn't, as the final a !=3D b assert fails.
>> Using 'int' and 'int &' we get:
>>
>> int target =3D 17;
>>
>> int & b =3D target;
>> int & a =3D b;
>> assert(a =3D=3D b);
>>
>> int & c =3D b;
>> change(a);
>> assert(c =3D=3D b && a !=3D b);  // fails! as a =3D=3D b
>
>
> Yes, raw references are not regular.
>
>>
>>
>> So does optional<int &> have the same semantics as int & (at least
>> when the optional is engaged)?
>> Except optional allows rebinding, whereas int & does not.
>
>
> Given this assignment semantics, it is impossible to say if optional
> references are 'like' raw references.

agreed

> They allow the same kind of departure
> from RegularType. One could say that the only purpose of raw references (=
and
> therefore also  optional references) is to depart from RegularType
> requirements (especially: the "value separation")
>

astute

>>
>>
>> Why not allow mixed assignment even?
>>
>> optional<int &> oi =3D target;
>> oi =3D 123;
>
>
> Here, you imply that the semantics would be non-rebinding:
>
> oi =3D 123 <=3D=3D>  *oi =3D 123
> (of course, if oi !=3D nullopt)
>

yes, non-rebinding (whether using literal 123 or a variable)

> But that would be inconsistent with converting constructor: which only bi=
nds
> a reference.

Yes! ie exact same as int &.  Assignment of int & is inconsistent with
its constructor:

int i =3D 0, j =3D 1;
int & a  =3D i;  // A
a =3D j;  // B - does not rebind!
assert(i =3D=3D 1);

Line A is inconsistent with B.  Maybe you call B "mixed assignment".
A is non-mixed:  int & =3D int &.  B is mixed: int & =3D int.  :-)

So optional could be the same.
optional<int &> a =3D i;    // A
a =3D j; // B

same as behaviour as int &.


So we could *almost* say optional<T&> is Regular, and Reference on
mixed-ops.  This is not inconsistent.  Regular only talks about T
w.r.t. T, not mixed types.
Also, pointers are similarly Regular but used for Reference.

(If the language had allowed:
int i;
int * pi =3D &i;
pi =3D 12;  // sets i to 12

would that be a problem? Confusion?  (If so, should optional dial back
its operators?)
Also, if references required notation to convert a variable from value
to ref, would this have allowed rebinding:

int i =3D 0, j =3D 1;
int & ri =3D @i; // or ref_of(i) or &i or whatever.
ri =3D j; // sets i to 1
ri =3D &j; // rebinds to j

But I digress.)


I say optional<T&> is *almost* Regular, because optional<T&> is NOT
Regular on =3D=3D.  Which is why I asked in the first place.
It may seem odd that optional<T&> =3D=3D optional<T&> would do something
like compare addresses, but it would make optional consistently
Regular in all cases.
Instead optional<> is Regular *everywhere*, including (non-mixed)
assignment, except:

=3D=3D on optional<T&>



> Also the existence of this assignment was the reason that
> caused the first revision of Optional to be rejected by the Committee.
>

Sure.  Is that a problem?  :-)  What do they/we know? :-):-)

>
>>
>> that would be consistent with int &.
>> I guess it gets confusing with the rebinding?
>>
>> int alternate =3D 21;
>> int another  =3D 35;
>> oi =3D alternate;
>> assert(target =3D=3D 21);
>> oi =3D optional<int&>(another);
>> oi =3D 42;
>> assert(target !=3D 42);
>> assert(another =3D=3D 42);
>
>
> rebinding mixed assignment is confusing -- true. Non-rebinding one is
> inconsistent with the homogenous assignment, though -- this would also be
> confusing.
>
>>
>> I could live with mixed assignment.  Moreover, I think it is "more
>> correct".
>
>
> Is the above statement correct? You are considering the mixed assignment
> because you could live with it?
>

As above, I think optional could be, maybe "strives" to be, Regular.
Mixed-ops don't count with Regular.  Regular only deals with T op T.
So mixed-ops can differ.
Furthermore, having mixed-assignment be Reference is consistent with int &.
Basically mixed assignment is always "I will pass this on to my
value_type, and it will do whatever it wants with it".
Which is consistent with *really mixed* assignment - ie when the value
is neither T nor optional<T>.  ie:

T t;
U u;
optional<T> ot =3D something_not_empty;

ot =3D u;

What does that do?  Is it the same as:

*ot =3D u;

ie calls T::operator=3D(U) (assuming it exists)?

So when T is int &, it would call, in effect, "int&::operator=3D(int)".
Which is non-rebinding.


(Also, going back to mixed <, I could see
opt < val  <=3D=3D> *opt < val
ie throws if not engaged.
Then T i; U u; opt<T> < U makes sense if T < U makes sense.  And
opt<T> < opt<T> is still fine as in your proposal.)

>>
>>
>> So generic code wants to work generically (obviously) and typically on
>> RegularTypes.  optional<> is not always regular.  How do I
>> compile-time check that the target type is a reference?  I assume
>> there is optional<>::value_type.  I don't expect that I can easily
>> test that the value_type is regular (in general) but I can check if it
>> is a reference.
>
>
> yes, optional provides this value_type. I am not sure I agree with this
> claim about the expectation that generic T is a RegularType. Consider
> InputIterator-s.

There was a "typically" up there.  I think most generic code relies on
RegularType.  If the code doesn't need it, great, but, like Stepanov
says, we often assume Regular and forget to even think about it - ie
we make a temp variable as needed, or do certain refactorings and
optimizations that rely on it.  Of course template writers are not
your "typical" coder, so they might keep non-Regular in mind, but the
average programmer assumes it without thinking.

>
>>
>>
>> Don't know what that says about your first argument in favour of
>> optional references:
>> "optional<T> can be used in generic code, were T can be either a
>> reference or an object"
>>
>> I don't think generic code will typically work with both optional<T>
>> and optional<T&> interchangeably. Nor do I think much generic code
>> works with T and T& interchangeably.  The semantics are different,
>> there isn't much of interest the generic code can reliably do.
>
>
> Well, I agree with you here. And therewith I disagree with the statement =
in
> my proposal :(
> Personally, I cannot imagine why I would want to treat optional<T> and
> optional<T&> generically. If you consider using
> is_reference<optional<X>::value_type>, this is in fact a departure from
> genericity. However, some users do insist on generic use. I hope, not onl=
y
> on insisting per se. One convincing example I was shown was the following=
:
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/cXneqUj-5oo/zC=
nKbHCGsxgJ
> That is, you only want to forward the T, whatever it is.
>

There will be cases like that, yes.  But not many. (Of course "no one
knows what the average programmer does"...)

>>
>> By the way, now that I've (re)read the Auxiliary part about optional
>> references, I see you've covered much of this.  Hope I wasn't
>> repeating too much, and something of the above was helpful.
>
>
> It was useful. For instance you reminded me that a swap for optional
> references should be re-enabled along with the assignment. Thanks!
>
>>
>>
>> And also the example:
>>
>> void assign_norebind(optional<T&>& optref, T& obj)
>> {
>>   if (optref) *optref =3D obj;
>>   else        optref.emplace(obj);
>> }
>>
>> Is that really useful?  It is 2 totally different semantics
>> ("targetting" vs "set-value-of-target") rolled into one.
>
>
> Some people insisted on this behavior for optional ref assignment. We do =
not
> propose it, but if you need it, we show you how to do it. Nothing more.
>
> Thank you for the input. I will improve the rationale section based on th=
is
> discussion.
>
> Regards,
> &rzej
>

As you may have guessed, I'm finding optional<> very interesting. :-)
Thanks for bringing it to the committee.
Tony

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/?hl=3Den.



.
