[Bug c++/104678] New: pointer to member cannot be passed as template argument after derived/base cast

schaumb at gmail dot com gcc-bugzilla@gcc.gnu.org
Thu Feb 24 15:03:11 GMT 2022


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

            Bug ID: 104678
           Summary: pointer to member cannot be passed as template
                    argument after derived/base cast
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: schaumb at gmail dot com
  Target Milestone: ---

If I has a pointer to member value, when I static cast to derived member
pointer then back to the original, it cannot be used as a template argument.


struct B { int m; };
struct D : B {};

template<int B::*>
struct X;

constexpr int B::* memptr = &B::m;
constexpr int B::* same_p = static_cast<int B::*>(static_cast<int
D::*>(&B::m));

static_assert(memptr == same_p, ""); // OK
// static_assert(std::is_corresponding_member(memptr, same_p)); // OK

using Good = X<memptr>; // OK
using Bad = X<same_p>; // error


fails with the following message:

error: '0' is not a valid template argument for type 'int B::*'
note: it must be a pointer-to-member of the form '&X::Y

as you can see here:

https://godbolt.org/z/oa3jY6c41


The C++20 ISO says:

§ 7.3.12, 2:

A prvalue of type “pointer to member of B of type cv T”, where B is a class
type, can be converted to a prvalue of type “pointer to member of D of type cv
T”, where D is a complete class derived (11.7) from B.

The result of the conversion refers to the same member as the pointer to member
before the conversion took place, but it refers to the base class member as if
it were a member of the derived class. The result refers to the member in D’s
instance of B.

The result is the same as if indirecting through the pointer to member of B
with the B subobject of D.


§ 7.6.1.7, 12:

A prvalue of type “pointer to member of D of type cv1 T” can be converted to a
prvalue of type “pointer to member of B of type cv2 T”, where D is a complete
class type and B is a base class (11.7) of D, if cv2 is the same
cv-qualification as, or greater cv-qualification than, cv1. 

If class B contains the original member, or is a base or derived class of the
class containing the original member, the resulting pointer to member points to
the original member. 



- All gcc version affected
- The problem is system independent
- The gcc compile options are not related
- command line: see at godbolt, g++ main.cpp
- error message: see above


More information about the Gcc-bugs mailing list