On Sat, 21 Jan 2023, 12:57 , <language.lawyer@gmail.com> wrote:
On 21/01/2023 17:49, Edward Catmur wrote:
> On Sat, 21 Jan 2023, 12:40 , <language.lawyer@gmail.com> wrote:
>
>> On 21/01/2023 17:37, Edward Catmur wrote:
>>> On Sat, 21 Jan 2023, 12:34 , <language.lawyer@gmail.com> wrote:
>>>
>>>> On 21/01/2023 17:31, Edward Catmur wrote:
>>>>> On Sat, 21 Jan 2023, 12:25 language.lawyer--- via Std-Proposals, <
>>>>> std-proposals@lists.isocpp.org> wrote:
>>>>>
>>>>>> On 20/01/2023 12:42, Jens Maurer via Std-Proposals wrote:
>>>>>>> On 20/01/2023 07.55, Julien Allali via Std-Proposals wrote:
>>>>>>>> Hi everyone,
>>>>>>>>
>>>>>>>> I checked the following code from one of my student:
>>>>>>>>
>>>>>>>> class I{
>>>>>>>> public:
>>>>>>>>        virtual ~I(){}
>>>>>>>>        virtual void print(){
>>>>>>>>          printf("hello %p\n",this);
>>>>>>>>        }
>>>>>>>>        virtual void f()=0;
>>>>>>>> };
>>>>>>>>
>>>>>>>> class B : public virtual I{
>>>>>>>>        int i,j;
>>>>>>>> public:
>>>>>>>>        ~B(){}
>>>>>>>>        virtual void f(){
>>>>>>>>          printf("B %p\n",this);
>>>>>>>>        }
>>>>>>>> };
>>>>>>>>
>>>>>>>>
>>>>>>>> void f(I *i){
>>>>>>>>        for(int j=0;j<5;++j)
>>>>>>>>          {
>>>>>>>>            i->print();
>>>>>>>>            i->f();
>>>>>>>>            printf("i=%p ",i);
>>>>>>>>            i++; // PROBLEM IS HERE
>>>>>>>>            printf(" => %p \n",i);
>>>>>>>>          }
>>>>>>>> }
>>>>>>>>
>>>>>>>> int main(){
>>>>>>>>        B b[]={B(),B()};
>>>>>>>>        printf("B: %p %p\n",b,b+1);
>>>>>>>>        f(b);
>>>>>>>> }
>>>>>>>>
>>>>>>>> As you can see, I is a non instantiable type as it has one pure
>>>> virtual
>>>>>>>> method. My concern is about the line "i++": I believed it will lead
>> to
>>>>>>>> an error or at least a warning (g++ 11.3.0)... Indeed, I can not
>>>> imagine
>>>>>>>> a valid case where doing arithmetic on a pointer of a type with pure
>>>>>>>> virtual function can be valid.... Shouldn't the standard forbid such
>>>>>>>> arithmetic?
>>>>>>>
>>>>>>> Why is the code iterating over 5 elements of a two-element array to
>>>>>>> start with?
>>>>>>>
>>>>>>> Anyway, the "i++" is undefined behavior per [expr.add] p6:
>>>>>>>
>>>>>>>> For addition or subtraction, if the expressions P or Q have type
>>>>>> “pointer to cv T”,
>>>>>>>> where T and the array element type are not similar (7.3.6), the
>>>>>> behavior is undefined.
>>>>>>
>>>>>> In f(b), first we get array-to-pointer conversion to get a pointer to
>>>> the
>>>>>> first array element, and then conversion to pointer to its I base
>> class
>>>>>> subobject, so the pointer type and the object it points to are
>> aligned.
>>>>>> Which means there is no UB per [expr.add]/6.
>>>>>>
>>>>>
>>>>> "similar" isn't specified in terms of alignment.
>>>>
>>>> "aligned" == "coherent/matching/in agreement"
>>>>
>>>
>>> I have no idea what you mean by that. Are you saying that the array
>> element
>>> type and the base class type are similar?
>>
>> I mean that doing pointer arithmetic on a «pointer to I» which points at
>> object of type I is OK from [expr.add]/6 POV.
>>
>
> The base class subobject and pointer type are similar, but the array
> element type is not.

How can T in «pointer to T» expression type be similar to the type of the base class subobject, and not similar to the «array element type» at the same time, when array element here is the base class subobject?

The array element type is B. The base class subobject type is I. These are different types.