Date: Sat, 27 Jul 2013 23:36:34 +0200
El 26/07/2013 21:22, Gabriel Dos Reis wrote:
> The oblique point I was making in the original reply was that C++'s
> model requires that we work with objects, which means we work with
> constructors and invariants guaranteed during construction or during the
> object's lifetime. Maybe that was too oblique :-(
>
> We don't have a notion of an object's value before it existed.
>
>
> I think so. It looks to me as if some of the "issues" raised in this
> discussion implicitly make the assumption that there is a notion of an
> object's value before its construction or lifetime, and such value is
> preserved after construction. If that is the case, then I think those
> issues are not properly formulated for C++'s fundamental object model.
Then it appears that a lot of system programming done in C/C++ relies on
UB and we can't find a correct way to achieve the same results with
similart performance. AFAIK, all current compilers still do what
programmers (wrongly) expect. So before optimizers start (correctly,
according to the language specification) banning such uses, we need to
formulate a simple way to allow low-level programming in C/C++, without
limiting too many optimization opportunities.
One straightforward way I can think of is to specify that the lifetime
of an object (3.8 Object lifetime [basic.life]) of type T begins also when:
-> the storage of unknown or [unsigned|signed] char static type with
proper alignment is obtained (*) OR a value of integral type or
enumeration type representing such storage is used.
AND
-> it's reinterpret_cast-ed to the type "pointer to T" (2)
(1) A poor effort to limit aliasing to char arrays and mmap-like
functions. With "unknown" data I would like to say void * storage
returned by some system calls, but I don't know how to exclude the
address of any storage converted to void*.
(2) reinterpret_cast is chosen so that in C, a simple C-cast could
achieve the same effect.
Then in the reinterpret_cast section (5.2.10 Reinterpret cast
[expr.reinterpret.cast]) a new pointer casting is allowed:
"Converting a prvalue of type “pointer to T1” to the type “pointer to
T2”, where “pointer to T1” is a pointer to an storage of unknown or
[unsigned|signed] char type with proper alignment and size to hold T2,
and T2 is an object type, the contents pointed by “pointer to T1” will
become the object representation for an object of type T2. If contents
of the storage are not a correct object representation for the object of
type T2, the cast results in undefined behavior."
Would somthing like this make any sense?
Best,
Ion
> The oblique point I was making in the original reply was that C++'s
> model requires that we work with objects, which means we work with
> constructors and invariants guaranteed during construction or during the
> object's lifetime. Maybe that was too oblique :-(
>
> We don't have a notion of an object's value before it existed.
>
>
> I think so. It looks to me as if some of the "issues" raised in this
> discussion implicitly make the assumption that there is a notion of an
> object's value before its construction or lifetime, and such value is
> preserved after construction. If that is the case, then I think those
> issues are not properly formulated for C++'s fundamental object model.
Then it appears that a lot of system programming done in C/C++ relies on
UB and we can't find a correct way to achieve the same results with
similart performance. AFAIK, all current compilers still do what
programmers (wrongly) expect. So before optimizers start (correctly,
according to the language specification) banning such uses, we need to
formulate a simple way to allow low-level programming in C/C++, without
limiting too many optimization opportunities.
One straightforward way I can think of is to specify that the lifetime
of an object (3.8 Object lifetime [basic.life]) of type T begins also when:
-> the storage of unknown or [unsigned|signed] char static type with
proper alignment is obtained (*) OR a value of integral type or
enumeration type representing such storage is used.
AND
-> it's reinterpret_cast-ed to the type "pointer to T" (2)
(1) A poor effort to limit aliasing to char arrays and mmap-like
functions. With "unknown" data I would like to say void * storage
returned by some system calls, but I don't know how to exclude the
address of any storage converted to void*.
(2) reinterpret_cast is chosen so that in C, a simple C-cast could
achieve the same effect.
Then in the reinterpret_cast section (5.2.10 Reinterpret cast
[expr.reinterpret.cast]) a new pointer casting is allowed:
"Converting a prvalue of type “pointer to T1” to the type “pointer to
T2”, where “pointer to T1” is a pointer to an storage of unknown or
[unsigned|signed] char type with proper alignment and size to hold T2,
and T2 is an object type, the contents pointed by “pointer to T1” will
become the object representation for an object of type T2. If contents
of the storage are not a correct object representation for the object of
type T2, the cast results in undefined behavior."
Would somthing like this make any sense?
Best,
Ion
Received on 2013-07-27 23:36:58