On Fri, Aug 23, 2013 at 10:34 PM, Mike Stump <[email protected]> wrote:
> On Aug 23, 2013, at 5:53 PM, Gabriel Dos Reis <[email protected]>
> 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 <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