On 2015/06/28 3:36, Jens Maurer wrote:
> On 06/27/2015 08:32 AM, Kazutoshi Satoda wrote:
>> I have some questions on the paper.
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4430.html
Second one is that the paper seems banning casts between pointer to a
class and pointer to its first subobject. There seems to be some C
programs that emulate class inheritance with such casts. For example:
https://stackoverflow.com/questions/415452/object-orientation-in-c/415536#415536
> struct base
> {
> /* base class members */
> };
>
> struct derived
> {
> struct base super;
> /* derived class members */
> };
>
> struct derived d;
> struct base *base_ptr = (struct base *)&d; // upcast
> struct derived *derived_ptr = (struct derived *)base_ptr; // downcast
I think these are valid C program, and C++ also allow them with some
special rules to keep compatibility with C. The paper seems like
removing one of them.
On 2015/06/28 16:11, Richard Smith wrote:
> Regarding 3.8/7: I don't see that any changes are required there. It
> continues to be the case that replacing an object of a class with reference
> or const members invalidates all pointers, references, and names that refer
> to the original object, in the sense that they cannot be used to access the
> new object. Accessing the new object starting from an old
> pointer/reference/name requires use of std::launder.
OK I got the idea of that. I should re-read the paper. Thank you.
If possible, I want to see a newer version of the paper or list of
feedbacks already given.
>> Is it good to send CC to the e-mail address in paper to post about a
>> paper? (I think it is good, but I forgot to do that this time.)
>
> This author reads std-proposals :) But yes, as general advice, you should
> contact the author of the paper when providing feedback; that's why the
> papers contain an email address for the author.
OK. I'll do that next time.
--
k_satoda
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
On Sat, Jun 27, 2015 at 8:52 PM, Kazutoshi Satoda <k_sa...@f2.dion.ne.jp> wrote:
First concern with C incompatibility is that the paper says "malloc
alone is not sufficient to create an object" as "the status quo". But
in C, malloc (or other allocation functions) is the only way to create
objects with dynamic storage duration. If changes (proposed and
foreseen) based on that "status quo" are accepted, many C programs will
be seen invalid with C++ compiler and may be broken silently.This paper does not change anything here. In C++, malloc has never created an object because [intro.object]/1 says that an object is *only* created by a new-expression, declaration, or when an implementation creates a temporary object (malloc is none of these). I agree that this is a problem, and it's very common to see programs do this:struct TrivialThing { int a, b, c; };TrivialThing *p = reinterpret_cast<TrivialThing*>(malloc());p->a = 0; // UB, no object of type TrivialThing hereI'll reiterate what the paper says: there is no change to the status quo here; the standard previously said this was UB, and still does. Fixing this (if the committee agrees that it is a bug) should be done by a separate paper.
The lifetime of an object is a runtime property of the object. An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivial default constructor. [Note: initialization by a trivial copy/move constructor is non-vacuous initialization. — end note] The lifetime of an object of type T begins when:
— storage with the proper alignment and size for type T is obtained; and
— if the object has non-vacuous initialization, its initialization is complete.
> struct derived d;
> struct base *base_ptr = (struct base *)&d; // upcast
> struct derived *derived_ptr = (struct derived *)base_ptr; // downcast
I think these are valid C program, and C++ also allow them with some
special rules to keep compatibility with C. The paper seems like
removing one of them.This was the subject of some debate. The previous draft of the paper intended to allow such casts in the cases where the standard guaranteed the addresses are the same (indeed, that seemed to be the purpose of such guarantees). We backed off this when it was observed that an existing C++ optimizer was already optimizing on the basis of such casts being invalid, based on a (reasonable) reading of the current wording of the standard.This probably warrants more debate by CWG. If possible, I'd like to guarantee that casting between a pointer-to-standard-layout-class and its first element gives a usable pointer value, and likewise for casting between a pointer to an array and its first element and for casting between a pointer to a union and any element type. This seems to be the intent of the current standard wording, even if a strict interpretation of the words could give another conclusion.
On Sunday, June 28, 2015 at 12:11:49 AM UTC-7, Richard Smith wrote:On Sat, Jun 27, 2015 at 8:52 PM, Kazutoshi Satoda <k_sa...@f2.dion.ne.jp> wrote:
First concern with C incompatibility is that the paper says "malloc
alone is not sufficient to create an object" as "the status quo". But
in C, malloc (or other allocation functions) is the only way to create
objects with dynamic storage duration. If changes (proposed and
foreseen) based on that "status quo" are accepted, many C programs will
be seen invalid with C++ compiler and may be broken silently.This paper does not change anything here. In C++, malloc has never created an object because [intro.object]/1 says that an object is *only* created by a new-expression, declaration, or when an implementation creates a temporary object (malloc is none of these). I agree that this is a problem, and it's very common to see programs do this:struct TrivialThing { int a, b, c; };TrivialThing *p = reinterpret_cast<TrivialThing*>(malloc());p->a = 0; // UB, no object of type TrivialThing hereI'll reiterate what the paper says: there is no change to the status quo here; the standard previously said this was UB, and still does. Fixing this (if the committee agrees that it is a bug) should be done by a separate paper.
Why is that undefined behavior in the current Standard? [basic.life]/1:The lifetime of an object is a runtime property of the object. An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivial default constructor. [Note: initialization by a trivial copy/move constructor is non-vacuous initialization. — end note] The lifetime of an object of type T begins when:
— storage with the proper alignment and size for type T is obtained; and
— if the object has non-vacuous initialization, its initialization is complete.
TrivialThing has vacuous initialization.
malloc(sizeof(TrivialThing)) allocates storage of the proper size. Only alignment remains as a concern, but without an alignas attribute, it isn't possible for a standard-layout structure to require an alignment greater than that guaranteed by malloc()'s definition.
If the argument is then about it not being "an object" until a new expression, that interpretation leads to a contradiction: how can the Standard talk about an object before its existence? It'd imply a contradiction in the Standard.
Looking at this, this proposal looks extremely bad for the future of C++, unless the intent is to fork C++ into a new managed language.
The ability to do some of the pointer manipulation banned by the proposal is relied upon by way too much code. In fact, C++ programmers are used to using these mechanisms to get work done, because it's sometimes the best tool for the job.
The above is extremely broken in particular: it means that many C libraries with such statements in macros or inline functions in header files can't be used in C++ programs anymore. If you try to use one of these C functions, the compiler will just willy-nilly delete your code from existence without warning.
Then there is the matter of pool allocators: with such strict rules on pointer manipulation, it's impossible to write a meaningful pool allocator or similar construction. Unless you want to write such things in C since C++ would be too strict to allow it.
Optimization is not the only goal — usability, versatility, intelligibility and self-consistency are also goals.> struct derived d;
> struct base *base_ptr = (struct base *)&d; // upcast
> struct derived *derived_ptr = (struct derived *)base_ptr; // downcast
I think these are valid C program, and C++ also allow them with some
special rules to keep compatibility with C. The paper seems like
removing one of them.This was the subject of some debate. The previous draft of the paper intended to allow such casts in the cases where the standard guaranteed the addresses are the same (indeed, that seemed to be the purpose of such guarantees). We backed off this when it was observed that an existing C++ optimizer was already optimizing on the basis of such casts being invalid, based on a (reasonable) reading of the current wording of the standard.This probably warrants more debate by CWG. If possible, I'd like to guarantee that casting between a pointer-to-standard-layout-class and its first element gives a usable pointer value, and likewise for casting between a pointer to an array and its first element and for casting between a pointer to a union and any element type. This seems to be the intent of the current standard wording, even if a strict interpretation of the words could give another conclusion.
Without support for this, struct sockaddr does not work.
Melissa
--