https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117615

            Bug ID: 117615
           Summary: constexpr failure static_cast of Derived virtual
                    Pointer to Member
           Product: gcc
           Version: 14.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: acox at reliablecontrols dot com
  Target Milestone: ---

Casting a virtual member function from the derived class fails to compile with
an error message complaining about a reinterpret_cast from a number to the
function signature. The number seems to be an offset, if you add a virtual
destructor to the Base class before the line doit is defined on the number
increases to 17.

https://godbolt.org/z/xPennWh15

<source>: In function 'int main()':
<source>:36:37:   in 'constexpr' expansion of 'help(&Derived::doit)'
<source>:28:7: error: 'reinterpret_cast<void (Base::*)(int) const>(1)' is not a
constant expression
   28 |     : mFn(static_cast<fn_t>(fn))
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~
Compiler returned: 1

It compiles under the following changes
- if the member functions are made non-virtual
- if constexpr is removed from h
- if h is constructed with &Base::doit

Code from the godbolt link is included below as well.

```
#include <iostream>

#define BREAK_IT

struct Base {
#ifdef BREAK_IT
    virtual
#endif
    void doit(int v) const { std::cout << "doit base " << v; }
        virtual ~Base() = default;

};

struct Derived : Base {
#ifdef BREAK_IT
    virtual
#endif
    void doit(int v) const { std::cout << "doit derived " << v; }
};

struct help
{
    using fn_t = void (Base::*)(int) const;

    fn_t mFn;

    constexpr help(auto && fn)
    : mFn(static_cast<fn_t>(fn))
    {

    }
};

int main()
{
    constexpr help h (&Derived::doit);
    Derived x;
    (x.*h.mFn)(12);
}
```

Reply via email to