union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff;//undefined behavior :-(
[[type-pun]] union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff; // compiler won't get too clever with optimizations, will do the obvious thing
// and source code analyzers will know that the type punning is deliberate.
So it's not uncommon to see people write code like this:
union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff;//undefined behavior :-(Of course this is met with those who are trilled that it works, and just as many others who are determined to avoid undefined behavior and would like to avoid it at all costs.Now that C++ has a proper attribute syntax. Has anyone considered having an attribute which says "I want to pun this type, compiler please don't get too clever here".
Of course by default we'd get the current rules about only having one active member at a time and all that goodness, allowing optimizers to assume that you won't do that and do clever things. And I recognize that there would still be concerns about endianess and such, but at least we've moved the issue from undefined behavior into "system specific" behavior, which low level developers tend to be comfortable with.
Mostly, the cleverness is aliasing analysis rather than anything pertaining to unions per se. I'm a little confused by the given example, as character types aliasing other types is explicitly permitted by the standard and given something close to the desired meaning already.
Also, is this attribute intended to have local or global effect? If local, then one can convert bitwise between types already using memcpy. If global, the problem is that in C, which is supposed to have those semantics, no compiler has ever implemented them and there is serious movement toward removing them from the next version of the C standard. I suppose this is because it's difficult to determine whether two function parameters could alias via a union and assuming they could has severe effects on performance.
> What will `x.u32` be after the two statements are executed? It's either undefined, implementation-defined, or well-defined. You want to rule out "undefined". So... what value does `x.u32` have? You say that it returns "the underlying bit-pattern interpreted as the appropriate type", but what does that mean?
That's easy enough; it has the value which if written to the object would exhibit the byte sequence present, if such a value exists. That's how memcpy works already in practice.
> In my experience, "low level developers" don't care that the above is undefined behavior; they'll do it anyway because they have no choice.
For bitwise conversion, they can use memcpy. For global aliasing... well, are they sure that's what they really want?
Who's to say that you haven't arranged that those bytes contain the object representation of some value of the destination type? Clearly this must be OK if the bytes arrive in the program from disk or network, so why not by modification of some other value's object representation?
Clearly this must be OK if the bytes arrive in the program from disk or network, so why not by modification of some other value's object representation.
Character types don't have tag bits, and other types might not either.
Consider this program:
int32_t a = 0x11223344;
char c[4];
memcpy(c, &a, 4);
int32_t b = 0x11223355;
char d[4];
memcpy(d, &b, 4);
if (d[0] == 0x55 &&
!memcmp(c + 1, d + 1, 3)) {
c[0] = 0x55;
memcpy(&a, c, 4);
assert(a == b);
}
Is this well defined? On a platform where the if block is entered?
I'm not saying that the result of bit-level hackery should be defined in all cases, just that it should be when the bit sequence would have been acceptable if it had arrived in the program by some other means.
I'm not saying that the result of bit-level hackery should be defined in all cases, just that it should be when the bit sequence would have been acceptable if it had arrived in the program by some other means.
On Sunday, March 6, 2016 at 7:19:02 PM UTC-5, Edward Catmur wrote:Consider this program:
int32_t a = 0x11223344;
char c[4];
memcpy(c, &a, 4);
int32_t b = 0x11223355;
char d[4];
memcpy(d, &b, 4);
if (d[0] == 0x55 &&
!memcmp(c + 1, d + 1, 3)) {
c[0] = 0x55;
memcpy(&a, c, 4);
assert(a == b);
}Is this well defined? On a platform where the if block is entered?
It's undefined, because the standard does not specify the representation of the data you put into `d`. You are allowed to copy it in from an `int32_t` and copy it out to an `int32_t`. But interpreting the bits as anything other than an `int32_t` (or something that is layout compatible with it) is undefined behavior.
So it became undefined behavior the moment you did `d[0] == 0x55`.
I'm not saying that the result of bit-level hackery should be defined in all cases, just that it should be when the bit sequence would have been acceptable if it had arrived in the program by some other means.
And when exactly would that be? If you got `d` via a read from a file, what you got was a byte stream. The data in that byte stream is defined by the stream reading function and the file data you read from. If you got it from a network, then the bytes are defined by the networking API.
In neither case is well-defined behavior for you to memcpy `d` into an `int32_t` unless you have certain knowledge that it came from someone else memcpy'ing an `int32_t` into a byte stream and saving it to a file or sending it across a network. And the "someone else" must be from the same C++ implementation (compiler, platform, etc) as yourself.
And if you do know that it was an `int32_t` that was memcpy'd across files/networks... it's still not well defined what it means to access any of that data as anything other than an `int32_t`.
On Mon, Mar 7, 2016 at 1:30 AM, Nicol Bolas <jmck...@gmail.com> wrote:On Sunday, March 6, 2016 at 7:19:02 PM UTC-5, Edward Catmur wrote:Consider this program:
int32_t a = 0x11223344;
char c[4];
memcpy(c, &a, 4);
int32_t b = 0x11223355;
char d[4];
memcpy(d, &b, 4);
if (d[0] == 0x55 &&
!memcmp(c + 1, d + 1, 3)) {
c[0] = 0x55;
memcpy(&a, c, 4);
assert(a == b);
}Is this well defined? On a platform where the if block is entered?
It's undefined, because the standard does not specify the representation of the data you put into `d`. You are allowed to copy it in from an `int32_t` and copy it out to an `int32_t`. But interpreting the bits as anything other than an `int32_t` (or something that is layout compatible with it) is undefined behavior.
So it became undefined behavior the moment you did `d[0] == 0x55`.How is that undefined behavior? Which rule or rules in the standard does it violate?
int x = 20;
if(x == 15)
doSomething();
int x = 20;
unsigned char b[sizeof(int)];
memcpy(b, &x, sizeof(int));
if(b[0] == 15)
doSomething();
And therefore, doing anything other than copying the array is not defined behavior by the standard. And is therefore undefined.
If you instead do:
int x = 20;
unsigned char b[sizeof(int)];
memcpy(b, &x, sizeof(int));
if(b[0] == 15)
doSomething();
What is the behavior of this program? The standard does not say. The standard does not define the what the "underlying bytes" that make up the value representation of `int` are. It does not define what exactly gets stored in `b`. It only defines that if you copy the array back to a layout-compatible type, you get the same value representation back.
And therefore, doing anything other than copying the array is not defined behavior by the standard. And is therefore undefined.
UB doesn't always mean "crash". It can mean "does the thing you want, but the standard doesn't guarantee anything". Many people write programs that rely on UB every day. Indeed, it's more or less impossible to write (for example) code that deals with endian issues without at some point relying on UB.
Have their been made new attempts in bringing type-punning through unions into C++?
On Friday, March 4, 2016 at 8:58:21 PM UTC+1, Evan Teran wrote:So it's not uncommon to see people write code like this:
union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff;//undefined behavior :-(Of course this is met with those who are trilled that it works, and just as many others who are determined to avoid undefined behavior and would like to avoid it at all costs.Now that C++ has a proper attribute syntax. Has anyone considered having an attribute which says "I want to pun this type, compiler please don't get too clever here".Something as simple as this:
[[type-pun]] union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff; // compiler won't get too clever with optimizations, will do the obvious thing
// and source code analyzers will know that the type punning is deliberate.
The meaning being that the compiler can expect the user to write to any field, and read from any other field and it should do the obvious thing and return the underlying bit-pattern interpreted as the appropriate type. Something which many compilers do anyway.
Of course by default we'd get the current rules about only having one active member at a time and all that goodness, allowing optimizers to assume that you won't do that and do clever things. And I recognize that there would still be concerns about endianess and such, but at least we've moved the issue from undefined behavior into "system specific" behavior, which low level developers tend to be comfortable with.Thoughts?
--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/mPFd9uLsus8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5df63738-279b-44ae-be59-6e729577000d%40isocpp.org.
On 17 Oct 2017 23:05, <arvid.g...@gmail.com> wrote:Have their been made new attempts in bringing type-punning through unions into C++?
On Friday, March 4, 2016 at 8:58:21 PM UTC+1, Evan Teran wrote:So it's not uncommon to see people write code like this:
union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff;//undefined behavior :-(Of course this is met with those who are trilled that it works, and just as many others who are determined to avoid undefined behavior and would like to avoid it at all costs.Now that C++ has a proper attribute syntax. Has anyone considered having an attribute which says "I want to pun this type, compiler please don't get too clever here".Something as simple as this:
[[type-pun]] union T {
uint8_t bytes[sizeof(uint32_t)];
uint32_t u32;
};
T x;
x.u32 = 0x11223344;
x.bytes[0] = 0xff; // compiler won't get too clever with optimizations, will do the obvious thing
// and source code analyzers will know that the type punning is deliberate.
The meaning being that the compiler can expect the user to write to any field, and read from any other field and it should do the obvious thing and return the underlying bit-pattern interpreted as the appropriate type. Something which many compilers do anyway.The problem is when you form a pointer to a member and write to a different member. Anyone using such an attribute would expect a read via that pointer to reflect the update, but this defeats type-based aliasing globally, since the translation unit containing the read may have no conception that the union even exists.This is, by the way, why some people involved in the C standard consider union type punning in that language to be a mistake.
Melissa
--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/mPFd9uLsus8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9f16bfc4-8b7b-4108-bff9-1d0c2147edd6%40isocpp.org.
On 19 Oct 2017 01:00, "Myriachan" <myri...@gmail.com> wrote:The optimizer people don't like us taking pointers to union members even when type punning isn't involved at all:Anyway, the question is really about what we're going to do now. We can't go back and change how struct sockaddr_in6, OSVERSIONINFOEXW, etc. work.That's up to the respective vendors. If they need to add private attributes to ensure that these quasi-union types continue to work as documented, then so be it. But there's no need to require such facilities to exist on platforms that don't have to support these APIs.
Note that in the case of sockaddr, all the compiler needs is to permit casts between sockaddr, sockaddr_storage and the various protocol address types. There is no particular need for unions to be involved per my understanding.
On Wednesday, October 18, 2017 at 5:17:51 PM UTC-7, Edward Catmur wrote:On 19 Oct 2017 01:00, "Myriachan" <myri...@gmail.com> wrote:The optimizer people don't like us taking pointers to union members even when type punning isn't involved at all:Anyway, the question is really about what we're going to do now. We can't go back and change how struct sockaddr_in6, OSVERSIONINFOEXW, etc. work.That's up to the respective vendors. If they need to add private attributes to ensure that these quasi-union types continue to work as documented, then so be it. But there's no need to require such facilities to exist on platforms that don't have to support these APIs.Name one "hosted" (rather than "freestanding") platform that doesn't use structures/unions in this way somewhere in their API.
Note that in the case of sockaddr, all the compiler needs is to permit casts between sockaddr, sockaddr_storage and the various protocol address types. There is no particular need for unions to be involved per my understanding.From compiler writers' perspectives, there is very little difference between these unions and structs with a common initial sequence that get reinterpret_cast among each other. As an example, comment 20 in the link I gave above shows Clang messing up when no unions are involved, in a similar situation to how struct sockaddr works with sa_family.
Melissa--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/mPFd9uLsus8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/81a9a9de-9fc7-480c-8cd2-263e2c4fae7d%40isocpp.org.
Hah. Well, if there's existing practice, there's something to standardize. But I don't think much more than the existing common initial sequence rule is really required.
this defeats type-based aliasing globally
On Wed, Oct 18, 2017 at 9:28 PM, 'Edward Catmur' via ISO C++ Standard - Future Proposals <std-pr...@isocpp.org> wrote:Hah. Well, if there's existing practice, there's something to standardize. But I don't think much more than the existing common initial sequence rule is really required.
David M. Gay's old dtoa code (in C) uses both union type punning and memcpy across object boundaries (starting in the middle of one object!) And indeed, it appears to have been made to stop working by modern compilers which started applying the aliasing rules: <http://patrakov.blogspot.com/2009/03/dont-use-old-dtoac.html>.
TBAA is a useful concept, it should not be purposefully be defeated.
Despite that, even if unions turn out to be not the best way to convert
between unrelated types, C++ should have a standard way which can be
used and taught. As of right now, 'memcpy' is the only working way.
I could think of a few ways:
- Making 'reinterpret_cast' work for converting between types,
which would not alias but strictly copy the bit-pattern into the
destination type (though, I could see how this pose a few
problems)
- Creating a new cast (for example 'bit_cast': https://godbolt.org/g/1PWp67),
which can act like type punning through unions did / does.
- Creating a new 'union' (or annotating a union), which restricts
it usages to only converting between types.
On 10/19, Hyman Rosen wrote:
> On Wed, Oct 18, 2017 at 9:28 PM, 'Edward Catmur' via ISO C++ Standard -
> Future Proposals <std-pr...@isocpp.org> wrote:
> >
> > Hah. Well, if there's existing practice, there's something to standardize.
> > But I don't think much more than the existing common initial sequence rule
> > is really required.
> >
>
> David M. Gay's old dtoa code (in C) uses both union type punning and memcpy
> across object boundaries (starting in the middle of one object!) And
> indeed, it appears to have been made to stop working by modern compilers
> which started applying the aliasing rules: <
> http://patrakov.blogspot.com/2009/03/dont-use-old-dtoac.html>.
>
> this defeats type-based aliasing globally
> >
>
> Yes! Defeat type-based aliasing (detection) now!
>
> --
> You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/mPFd9uLsus8/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdZ6NUV5ypE-0AOfnJPoDxzq_4HNXVz0AWGAk6SaLNfn7w%40mail.gmail.com.
Arvid Gerstmann
Website: https://arvid.io | Skype: leandros9999
Twitter: https://twitter.com/ArvidGerstmann
--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/mPFd9uLsus8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20171019152630.GA44508%40mjolnir.local.
On 19 Oct 2017 01:44, "Myriachan" <myri...@gmail.com> wrote:On Wednesday, October 18, 2017 at 5:17:51 PM UTC-7, Edward Catmur wrote:On 19 Oct 2017 01:00, "Myriachan" <myri...@gmail.com> wrote:The optimizer people don't like us taking pointers to union members even when type punning isn't involved at all:Anyway, the question is really about what we're going to do now. We can't go back and change how struct sockaddr_in6, OSVERSIONINFOEXW, etc. work.That's up to the respective vendors. If they need to add private attributes to ensure that these quasi-union types continue to work as documented, then so be it. But there's no need to require such facilities to exist on platforms that don't have to support these APIs.Name one "hosted" (rather than "freestanding") platform that doesn't use structures/unions in this way somewhere in their API.Hah. Well, if there's existing practice, there's something to standardize. But I don't think much more than the existing common initial sequence rule is really required.
Are you aware of the bit_cast proposal? https://wg21.link/p0476
On Wednesday, October 18, 2017 at 6:28:41 PM UTC-7, Edward Catmur wrote:On 19 Oct 2017 01:44, "Myriachan" <myri...@gmail.com> wrote:On Wednesday, October 18, 2017 at 5:17:51 PM UTC-7, Edward Catmur wrote:On 19 Oct 2017 01:00, "Myriachan" <myri...@gmail.com> wrote:The optimizer people don't like us taking pointers to union members even when type punning isn't involved at all:Anyway, the question is really about what we're going to do now. We can't go back and change how struct sockaddr_in6, OSVERSIONINFOEXW, etc. work.That's up to the respective vendors. If they need to add private attributes to ensure that these quasi-union types continue to work as documented, then so be it. But there's no need to require such facilities to exist on platforms that don't have to support these APIs.Name one "hosted" (rather than "freestanding") platform that doesn't use structures/unions in this way somewhere in their API.Hah. Well, if there's existing practice, there's something to standardize. But I don't think much more than the existing common initial sequence rule is really required.From the way Richard Smith and Hal Finkle talked about it in the Clang bug I linked, it sounded like they wanted to change the rule such that the common initial sequence rule is only valid if you access the "wrong type" through the union type. This breaks sockaddr, because you don't pass a pointer to a union type, you pass a pointer to the sockaddr. Also, most programs declare e.g. a sockaddr_in6, then just reinterpret_cast the pointer to sockaddr * for calling connect(), rather than have a union at all. (I personally use a union for such code, but it's never been required.)
I am sure that plenty of "what people really want to do" would be satisfied by bit_cast as presented. For example, the dtoa you mention above could readily be implemented in terms of a value-semantic bit_cast.
On Thu, Oct 19, 2017 at 8:16 PM, Myriachan <myri...@gmail.com> wrote:On Wednesday, October 18, 2017 at 6:28:41 PM UTC-7, Edward Catmur wrote:On 19 Oct 2017 01:44, "Myriachan" <myri...@gmail.com> wrote:On Wednesday, October 18, 2017 at 5:17:51 PM UTC-7, Edward Catmur wrote:On 19 Oct 2017 01:00, "Myriachan" <myri...@gmail.com> wrote:The optimizer people don't like us taking pointers to union members even when type punning isn't involved at all:Anyway, the question is really about what we're going to do now. We can't go back and change how struct sockaddr_in6, OSVERSIONINFOEXW, etc. work.That's up to the respective vendors. If they need to add private attributes to ensure that these quasi-union types continue to work as documented, then so be it. But there's no need to require such facilities to exist on platforms that don't have to support these APIs.Name one "hosted" (rather than "freestanding") platform that doesn't use structures/unions in this way somewhere in their API.Hah. Well, if there's existing practice, there's something to standardize. But I don't think much more than the existing common initial sequence rule is really required.From the way Richard Smith and Hal Finkle talked about it in the Clang bug I linked, it sounded like they wanted to change the rule such that the common initial sequence rule is only valid if you access the "wrong type" through the union type. This breaks sockaddr, because you don't pass a pointer to a union type, you pass a pointer to the sockaddr. Also, most programs declare e.g. a sockaddr_in6, then just reinterpret_cast the pointer to sockaddr * for calling connect(), rather than have a union at all. (I personally use a union for such code, but it's never been required.)Well, that would be consistent, at least. As Hal Finkel says, if compilers break APIs like sockaddr, the solution to would be to add appropriate attributes. After all, vendors aren't going to break APIs that they document as supported.
On Thu, Oct 19, 2017 at 5:11 PM, 'Edward Catmur' via ISO C++ Standard - Future Proposals <std-pr...@isocpp.org> wrote:I am sure that plenty of "what people really want to do" would be satisfied by bit_cast as presented. For example, the dtoa you mention above could readily be implemented in terms of a value-semantic bit_cast.
People want to work in place, not copy back and forth.
That's been true ever since Fortran had an EQUIVALENCE statement.
And why is bit_cast restricted to trivially copyable types anyway?
Why shouldn't I be able to muck around with class innards,
including vtables and references and such, if I want to?
Humm ... no, because placement new is not guaranteed to preserve the contents of ptr ?
--
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-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/e314d818-3a7c-4057-97ae-b1ec7b0b8c41%40isocpp.org.
Actually, I wasn't precise enough.I meant "the contents pointed by ptr are not guaranteed to be preserved", which is what you've explained with "It is the initialization of the object inside that memory which is not guaranteed to preserve the contents of that memory."What I would understand that the pointee of `new(ptr) auto(bit_cast<other_type>(ptr));` good to write to, but never to read from.Are you saying that `bit_cast` circumvent that limitation by "memcpy initializing" the pointee with its own contents?
If you check the code generated by the popular compilers, you will see that `bit_cast` doesn't really copy anything (despite containing a memcpy).
Returning a value is optimized into a register load from the source. That's it.
And float_val = std::nextafter(float_val) is too self-explanatory?
This https://github.com/ifduyue/musl/blob/master/src/math/nextafter.c
Again, this is standard library code which doesn't have to be portable. It is not UB if your specific compiler defines the behavior.
On Sat, Oct 21, 2017 at 6:16 AM, Bo Persson <b...@gmb.dk> wrote:Again, this is standard library code which doesn't have to be portable. It is not UB if your specific compiler defines the behavior.It's something that wants to be an implementation of a standard library
function, but it's not an implementation by a specific compiler vendor.
More to the point, if people trying to write useful code have to write
non-portable code that exhibits UB by the language standard but not
by the specific compiler, that very much suggests that the language
standard is deficient or wrong.
And even more to the point, having this sort of UB in the language
allows new versions compilers, influenced by the optimizationists,
to silently break existing code, as happened with old versions of dtoa.
And yet even more, the language of the standard that purports to define
legal and portable code is so impenetrable that it is impossible to know ifa program is obeying the rules or not.
--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/mPFd9uLsus8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposals+unsubscribe@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAHSYqdbnKjZi3qji%3DwiMHkYi1dH%3DZzZ08oNnXPU1hBV%3D35XMjA%40mail.gmail.com.
Most useful code is not attempting to reinvent a wheel already provided by vendors.
On Tue, Oct 24, 2017 at 2:36 AM, 'Edward Catmur' via ISO C++ Standard - Future Proposals <std-pr...@isocpp.org> wrote:Most useful code is not attempting to reinvent a wheel already provided by vendors.
Dismissing as irrelevant every piece of code written in a style that you don't
like is not a good way to convince people who don't already believe you of the
correctness of your views.
I don't care that type-based alias analysis may let compilers make code run
faster. Those compilers have broken programs that had been behaving as
their authors expected for literal decades. Those compilers have introduced
security errors by removing code that relied on signed integer overflow wrapping.
I think it's only recently that they have started emitting warnings in some cases
about what they're doing, and then they get the warnings wrong:
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55217>.
People on these lists, who are presumably much more expert in C++ than the
average bear, have trouble agreeing on whether some piece of code has defined
behavior. But we are expected to trust that compiler programmers are getting
this right and are not going to be introducing silently lurking errors into compiled
code.
The standardization process is encouraging vendors to make brittle and broken
tools that fail to carry the intent of the programmers into the compiled programs.
The standardization process is wrapping itself into knots trying to express the
inexpressible. And all so that optimizationists can point and say "look at that!"