Date: Sat, 21 Jan 2023 17:25:25 +0500
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.
> 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.
Received on 2023-01-21 12:25:33