On Fri, Aug 23, 2013 at 10:34 PM, Mike Stump <mikest...@comcast.net> wrote:
> On Aug 23, 2013, at 5:53 PM, Gabriel Dos Reis <g...@integrable-solutions.net> 
> wrote:
>> If you quoted the standard to back up your assertions, I would have been
>> able to "feel free to point this out" :-)
>>
>> The thing is I am still trying to figure out what (1) what you would have 
>> liked;
>
> I've directly stated it, not sure how you missed it.  The life of the 
> original object does not end.

You made a statement.  It was not clear whether it was what you want
or whether it is what the standards mandate.

>> (2) what you believe the standards mandate, with appropriate quote; and
>
> The life of the original object does not end.  See below for the quote.

Your assertion or a quote from the standards?

>
>>>> Really?
>>>
>>>>> statement, or, is it merely changing the value?
>>>>
>>>> That is an assignment to an existing int storage.
>>>
>>>>> And what if we do a memcpy (ip, &j, sizeof (int));
>>>>
>>>> Well, the case of 'memcpy' isn't defined by the standard
>>>
>>> Odd, in the c++98 standard memcpy was defined by the standard, as well as 
>>> the open code that memcpy would be.  I find memcpy in [diff.library].  I 
>>> can quote all the requirements that makes the open code work as well.  It 
>>> is defined.
>>
>> When I say "the case of 'memcpy' isn't defined", I was not saying that
>> the function "memcpy" itself isn't defined by the standard.  I was discussing
>> its effect in the scope of this discussion, e.g. lifetime vs. assignment.
>> That isn't defined in the standard.
>
> And yet memcpy is exactly defined and all interactions with the entire rest 
> of the standard are as specified.  Those semantics that are defined and 
> required, are, by definition.  You can't make them go away by claiming they 
> are undefined.

I have no idea what exactly you are talking about.
If you have a rule in that standards that say that mempcy is assignment,
please share it with us.

>
> int i = 1, j = 2;
> {
>         memcpy (&i, &j)
>         // here i exists and is 2.
> }
>
>   3.7.1  Static storage duration                      [basic.stc.static]
>
> 1 All  objects which neither have dynamic storage duration nor are local
>   have static storage duration.  The storage  for  these  objects  shall
>   last   for   the   duration   of   the   program  (_basic.start.init_,
>   _basic.start.term_).
>
> This covers why i exists.

The storage duration of an object is not necessarily the same
as its lifetime.

>  As for why i has the value 2, gosh:
>
>        7.21.2.1  The memcpy function
>
>        Synopsis
>
>        [#1]
>
>                #include &lt;string.h>
>                void *memcpy(void * restrict s1,
>                        const void * restrict s2,
>                        size_t n);
>
>        Description
>
>        [#2] The memcpy function copies n characters from the object
>        pointed  to  by  s2  into  the  object pointed to by s1.  If
>        copying  takes  place  between  objects  that  overlap,  the
>        behavior is undefined.
>
>
>   1.6  The C++ memory model                               [intro.memory]
>
> 1 The fundamental storage unit in the C++ memory model is the  byte.
>
> An object  of  POD4)  type
>   (_basic.types_) shall occupy contiguous bytes of storage.
>
>  5.3.3  Sizeof                                            [expr.sizeof]
>
> 1 The sizeof operator yields the number of bytes in the object represen-
>   tation of its operand.  The operand is either an expression, which  is
>   not  evaluated, or a parenthesized type-id.  The sizeof operator shall
>
> 4 The  object representation of an object of type T is the sequence of N
>   unsigned char objects taken up by the object of type T, where N equals
>   sizeof(T).   The  value representation of an object is the set of bits
>   that hold the value of type T.  For POD types, the  value  representa-
>   tion  is  a set of bits in the object representation that determines a
>   value, which is one discrete element of an implementation-defined  set
>   of values.37)

Yes, but what is the relevance?

>
>>> You can see evidence that we meant for it to work here:
>>>
>>> 2 For any complete POD object type T, whether or not the object holds  a
>>>  valid value of type T, the underlying bytes (_intro.memory_) making up
>>>  the object can be copied into an array of char or unsigned char.36) If
>>>  the content of the array of char or unsigned char is copied back  into
>>>  the  object,  the  object  shall subsequently hold its original value.
>>>  [Example:
>>>  #define N sizeof(T)
>>>  char buf[N];
>>>  T obj;                          // obj initialized to its original value
>>>  memcpy(buf, &obj, N);           // between these two calls to memcpy,
>>>                                  // obj might be modified
>>>  memcpy(&obj, buf, N);           // at this point, each subobject of obj of 
>>> scalar type
>>>                                  // holds its original value
>>>
>>> thought, I view this as completely redundant with the standard and should 
>>> just be a note.  From the base standard, in C99 is it defined in 7.24.4.2.3 
>>> and I suspect remains largely unchanged from previous standards.
>>>
>>
>> This does not say whether the effect of memcpy is assigment or copy
>> construction.
>
> Right, because it doesn't define taking the bytes of one object and assigning 
> another object to have those bytes.  The definition of memcpy does that.

Chapter and verse, please.

>
> char c1, c2;
>
> c1 = c2;
>
> This is defined to take the bytes that comprise c2 (1 byte, by definition), 
> and slam them into c1.  After this runs, c1 will have the value of c2.  This, 
> is, by definition.  We can plainly see the assignment operator.  This is 
> assignment, the hint is the spelling of the operator.  It is spelled =.  This 
> is what the C standard means, when they say copies.  copies is defined to 
> mean, =.

so?  What is the relevance exactly?

>
>> Which was the point I was making.
>
> Sure it does.  Directly, please read the statement again:
>
>       The memcpy function copies n characters from the object
>       pointed  to  by  s2  into  the  object pointed to by s1.

Yes,  but why is that assignment not copy construction as in

     new (p) T (v);

?

That is the question.

> I said what the words mean.  I'd said copy means the = operator.

Copy in C++ does not necessarily mean assignment.

> Here is the text for =:
>
>        [#3] An assignment operator stores a  value  in  the  object
>        designated  by  the  left operand.

This does not say that storying a value in an object is assignment.

> This is the very definition of the word copy, trust me.  This is how the 
> standard was meant to be read.

See above.

>
>>>>> I think the most logical line of reasoning is that when the requirements 
>>>>> of [basic.lval] are met, the, this is a change of value of an object, not 
>>>>> a modification to it's lifetime.
>>>>
>>>> Why?
>>>
>>> Because if you end the lifetime of the original int, you destroy the 
>>> semantic that everyone knows for C.  This cannot be done.
>>
>> But:
>>  (1) we are not talking about C
>
> Sure we are.

No, we are not.  Please look back at my original message that you replied to.

> The semantics of memcpy and its behavior come from C, and are identical to 
> it.  Since this is true, I can freely quote the required semantics of the C 
> standard, they are identical.
>
>>  (2) C does not have a notion of lifetime -- at least not in the sense of 
>> C++.
>
> It absolutely does:  Let me quote:
>
>        [#1]  An  object  has a storage duration that determines its
>        lifetime.

Please give the definition of 'lifetime'.

>
>        [#17]  Note  that if a for loop were used instead of a while |
>        loop, the lifetime of the unnamed object would be  the  body
>        of  the  loop only, and on entry next time around p would be
>        pointing to an object  which  is  no  longer  guaranteed  to |
>        exist, which would result in undefined behavior.
>
>        expression  is  evaluated.   The  size of each instance of a
>        variable length  array  type  does  not  change  during  its
>        lifetime.
>
>
>        214The buffer has to have a lifetime at least  as  great  as
>           the  open stream, so the stream should be closed before a
>           buffer that has automatic storage duration is deallocated
>           upon block exit.
>
>        environment.    All  objects  in  static  storage  shall  be
>        initialized (set to their  initial  values)  before  program
>        startup.   The  manner and timing of such initialization are
>
>        [#5] An instance  of  each  object  with  automatic  storage
>        duration is associated with each entry into its block.  Such
>        an object exists and retains its  last-stored  value  during
>        the  execution of the block and while the block is suspended
>        (by a call of a function or receipt of a signal).
>
>        [#2] The malloc function allocates space for an object whose
>        size is specified by size and whose value is  indeterminate.
>
>          -- The value of a pointer that refers to space deallocated
>             by a call to the  free  or  realloc  function  is  used
>             (7.20.3).
>
>        [#2] The free function causes the space pointed to by ptr to
>        be  deallocated,  that  is,  made  available   for   further
>        allocation.

But this is not the lifetime in the C++ sense.

> I'll note that C++ merely sought to explain and formalize the rules of C.

Strongly disagree with that note.

> We extended and added a few bits, but, the object model is based upon the C 
> model.

The object model may have been based on C, but it went way beyond C in say that
C++ object model is expressible in C any more -- think empty base optimization.
This isn't just a few bits.

> I can't begin to fathom how you could have possibly missed the notion of 
> lifetime in C.

Most likely because I didn't miss it.

>  It right there, an just about exactly matches C++.

Not at all.  We tried to make certain constructs have similar byte-level
interpretation, but the conceptual models are completely different.

>
>> So, whatever notion of semantics you think everyone knows of C
>> is largely irrelevant.
>
> No, you must not understand C++ to say this.

Guilty as charged.  I must also confess that I do not know of any
body who understands C++ -- not even the collective body of the
C++ standards committee.

>  C++ is defined to be, exactly what C is,

I cannot understand the source of this confusion.

> with a few exceptions here and there, and in this case, there are no 
> exceptions.  This is by design.  I'm sorry if you didn't realize this.
>

Please don't be sorry, the confusion isn't necessarily where you believe it is.

>>>>> So, in the case quoted, since the type of the accesses are both int, we 
>>>>> don't reuse the storage, since the requirements of [basic.lval] are met.
>>>>
>>>> Consider:
>>>>
>>>>   struct S {
>>>>       S(int);
>>>>       ~S();
>>>>       // …
>>>>   };
>>>>
>>>>   int main() {
>>>>       S s(8);
>>>>
>>>>        new (&s) S(9); // #1
>>>>   }
>>>>
>>>> Is #1 a reuse of storage to create a new object or assignment?
>>>
>>> Behaves as assignment, s exists post the new, til the closing }.
>>
>> What does not mean concretely?
>
> Concretely, it means exactly what is stated in the standard.

Great!  The standards does not state it is assignment.

> I've quoted all the words.  copy means =.

No; I am sorry but you are plain wrong on this.

> = is an assignment operator.

Yep, and C++ makes a distinction between copy and assignment.

>  Concretely, where did you get lost?

Trying to connect what the standards say and your assertions.


> In the //, one can imagine you're asking about
>
> S (int v) { val = v; }
> int val;

That is one possible imagination; but it isn't the only one.

> to be concrete.  We can see the = operator.

In that imagination you just created, yes.   But it wasn't there
to begin with.

> This is the assignment operator, by definition.

Yes, but see above.

>>>>> Indeed, the programmer expects that they can access i after *ip = j; and 
>>>>> that the _value_ that object, while changed from the original 1, will be 
>>>>> 2 just after the *ip = j; statement.
>>>>>
>>>>> Since we know that i must be 3 at the end, we then know what the wording, 
>>>>> reused, must mean, cause other meanings that could possibly make it work 
>>>>> for you in the case you are considering, would destroy this property of 
>>>>> pointers, and everyone knows the semantics of pointers, they are 
>>>>> undisputed.  Or put another way, you cannot misread reused in this way.
>>>>
>>>> And why do you assert that I misread 'reused' in this way?
>>>
>>> See your email that I originally replied to.
>>>
>>> Let me quote it here:
>>>
>>>> If the user-supplied operator new returns &a, then it must
>>>> also ensure that 'a' is not used anywhere else -- e.g. I you can't
>>>> do lvalue-to-value conversion on 'a' to see what is written there.
>>>> Because its storage has been reused.
>>>
>>> You said it was reused, this is wrong.
>>
>> You keep saying it is wrong without quoting the standards that is the
>> basis for that.
>
> I've quoted the required semantics of the standard.  What part was unclear to 
> you?

See above.

>
>>> You use that as backing to say that the lifetime of the original object 
>>> ends, this is wrong.
>>
>> You *assert* it is wrong.
>
> I quoted the required semantics of the language standard. What part was 
> unclear to you?

The part where you assert imaginary things :-)

-- Gaby

Reply via email to