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".