Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c++ Subject: Re: C++20 concepts rocks Date: Tue, 15 Feb 2022 00:10:42 -0800 Organization: A noiseless patient Spider Lines: 91 Message-ID: <86zgmsh7nh.fsf@linuxsc.com> References: <87k0easj5d.fsf@bsb.me.uk> <865yptlpgf.fsf@linuxsc.com> <87mtj4qd0h.fsf@bsb.me.uk> <86fsovkdjw.fsf@linuxsc.com> <877da7r7ap.fsf@bsb.me.uk> <86bkzjjs3c.fsf@linuxsc.com> <87k0e6q4j8.fsf@bsb.me.uk> <8635kukb17.fsf@linuxsc.com> <878rumptie.fsf@bsb.me.uk> <86leymiga7.fsf@linuxsc.com> <877da3n2au.fsf@bsb.me.uk> <86czjvi97y.fsf@linuxsc.com> <87czjulvm9.fsf@bsb.me.uk> <868ruhikqf.fsf@linuxsc.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="2ced22d51f2768d5f155d420840b05f4"; logging-data="17944"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18kLFVFW7gmn9Nu744s+eCxaMjSTcGdwDQ=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:TTAuveF5DdVMEJ/KbtWp3Yu/vZQ= sha1:QyWpVXf8PpExI4EV9QIyVGT4fZM= Xref: csiph.com comp.lang.c++:83002 "Alf P. Steinbach" writes: > On 11 Feb 2022 14:41, Tim Rentsch wrote: > >> Ben Bacarisse writes: >> >>> Tim Rentsch writes: >>> >>>> Rather than thinking about pointer values, it might help to start >>>> with objects. [..illustrative examples..] >>>> >>>> Casting a pointer to a different type doesn't change what objects >>>> it can access. At least, this rule holds in C, [...] >>> >>> Really the only issue I had is resolved by the rule that "the array" is >>> always the smallest enclosing array that contains the thing pointed to >>> (before any conversions of course). >> >> Interesting. I hadn't thought of it that way before. Seems right. >> >> I should make a clarifying statement about casting not changing >> what objects can be accessed. If we have this code fragment >> >> int foo[10][20]; >> extern void set_elements( int *, size_t, int ) >> >> set_elements( (int*) &foo, 10*20, -1 ); >> >> an argument could be made that set_elements() cannot use pointer >> arithmetic (including that implied by use of []) on its first >> argument other than to access between foo[0][0] and foo[0][19] (or >> to construct a pointer to foo[0][20]). The reasoning would be that >> there is no array of 200 elements, so the conditions for address >> arithmetic would not be met for index values other than between 0 and >> 20, and so would technically be undefined behavior. > > First, for C++20 the above `reinterpret_cast`-expressed-as-C-cast > suffers from not involving "interconvertible" pointers, as noted in > 6.8.2/4.4: > > "An array object and its first element are not > pointer-interconvertible, even though they have the same address." Amusing. The language guarantees that the addresses line up, and then says the cast isn't guaranteed to work (apparently that is a change since C++14) even though it obviously will. Too funny for words. > Formally notes are not part of the formal language specification, > they're not "normative". [...] It seems clear that what the "Note" says follows from other normative text. > [...] > >> It would be >> surprising if that putative undefined behavior would result in the >> code "doing the wrong thing", but I feel obliged to point out the >> possible alternative reading nonetheless. >> >> Even if the reading proposed above holds, set_elements() can be >> written in a way that avoids the putative undefined behavior: >> >> void >> set_elements( int *v, size_t n, int value ){ >> while( n-- > 0 ){ >> *(int*)( (char*)v + n * sizeof *v ) = value; >> } >> } >> >> This code has to work for the call that passes '(int*)&foo', >> because all objects have an implied character array that overlays >> the entire object, which is all of foo in this case. > > Again, for C++ (though I understand you're discussing the C case) > you're colliding with a formal brick wall. > > The general consensus is that only `memcpy` plus one more mechanism I > don't recall now (citing lack of coffee plus excessive blood sugar > etc.) is sufficiently formally supported to avoid formal UB for > copying bytes of objects. There is no copying of bytes in the above code. > In particular a `reinterpret_cast`, in the above code expressed as a C > style cast, is a good way to let loose the strict aliasing demons of > the g++ compiler. [...] In the context the above code is used, there are no violations of type-based aliasing rules. Hence no "strict aliasing demons".