Bug 113308 - derived class doesn't currently allow inherited explicit object member function post increment operator
Summary: derived class doesn't currently allow inherited explicit object member functi...
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-01-10 12:40 UTC by Desmond Gold
Modified: 2024-01-11 21:46 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Desmond Gold 2024-01-10 12:40:18 UTC
With the recent support of explicit object parameter functions, inheriting explicit object member functions from base class seems to work except for post increment operator 'operator++(int)'.

struct add_fn
{
    template <typename Self>
    Self operator++(this Self&& self, int)
    {
      auto temp = self;
      ++self;
      return temp;
    }
};

struct A : add_fn 
{
    int n;
    A(int n) : n(n) {}

    A& operator++() 
    {
      ++n;
      return *this;
    }

    // this doesn't work either:
    // A& operator++(this A& self)
    // {
    //   ++self.n;
    //   return self;
    // }
};

int main()
{
    A a { 5 };
    ++a; // ok
    a++; // error: no 'operator++(int)' declared for postfix '++'
}

godbolt link: https://godbolt.org/z/1h57Thvds
Comment 1 Nathaniel Shead 2024-01-10 13:33:06 UTC
I believe this is correct behaviour: The definition of `operator++` in the child class hides the `operator++` declared in the base class. Similarly to the following code:


struct base {
  void f(int) {}
};
struct d1 : base {
  void f() {}
};
struct d2 : base {
  using base::f;  // explicitly add base::f as an overload
  void f() {}
};

int main() {
  d1{}.f(10);  // error
  d2{}.f(10);  // OK
}
Comment 2 waffl3x 2024-01-10 17:55:34 UTC
(In reply to Nathaniel Shead from comment #1)
> I believe this is correct behaviour: The definition of `operator++` in the
> child class hides the `operator++` declared in the base class. Similarly to
> the following code:
> 
> 
> struct base {
>   void f(int) {}
> };
> struct d1 : base {
>   void f() {}
> };
> struct d2 : base {
>   using base::f;  // explicitly add base::f as an overload
>   void f() {}
> };
> 
> int main() {
>   d1{}.f(10);  // error
>   d2{}.f(10);  // OK
> }

I'm pretty sure Nathaniel is right,
https://godbolt.org/z/d4r3dTsqa
https://godbolt.org/z/sxz1rcGbb
Mind you, clang and msvc's implementations are buggier than mine so I'm
not going to say "doesn't work on theirs so it isn't a bug" but I don't
think this one is a bug.

Thank you for testing my patch though, I do appreciate it.
Comment 3 waffl3x 2024-01-10 18:20:22 UTC
I meant to post this link instead of one of the others.
https://godbolt.org/z/oMP8185Yh
I guess I shouldn't be replying to things while still waking up, sorry!
Comment 4 Jonathan Wakely 2024-01-11 21:46:00 UTC
Yes, I think gcc is correct here. Explicit object functions aren't immune to name hiding.