This site uses cookies to deliver our services and to show you relevant ads and job listings.
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.
Your use of Stack Overflow’s Products and Services, including the Stack Overflow Network, is subject to these policies and terms.

Join us in building a kind, collaborative learning community via our updated
Code of Conduct.

2 Answers
2

The result of the unary & operator is a pointer to its operand. The
operand shall be an lvalue or a qualified-id. If the operand is a
qualified-id naming a non-static or variant member m of some class C
with type T, the result has type “pointer to member of class C of type
T” and is a prvalue designating C​::​m.

The qualified id you used is D::f, but it names a member function of B (I can bring up the lookup rules if you want). So the class type C in the above paragraph, is B. The type therefore resolves to void ( B::* )(void).

I was unconvinced initially, but I see from [class.mem] - "The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere." - that f is unequivocally a member of B and not a member of D, despite the D:: nested-name-specifier.
– fizzerNov 9 '17 at 12:57

The rationale behind this is that otherwise you won't be able to assign a value of &D::f to a variable of void ( B::* )(void) type without a cast even though f is a member of B or compare &D::f == &B::f.

For me, it is hard to accept the rationale. If I'd want to assign &D::f to a B::*, then I'd refer it as &B::f. This behavior of C++ is unexpected, I've met this phenomenon several times in the past. Why does the type of &D::f change whether there is an actual f in D? I understand the working behind this, but cannot accept it. As a user of B & D, I don't care, whether the person who created B or D added an f to D or not.
– gezaNov 9 '17 at 12:27

4

an easier workaround would be foo<D>(&D::f, &D::g)
– CAFNov 9 '17 at 14:08

1

@geza But this way &D::f == &B::f is correctly evaluated to true which makes perfect sense to me because f refers to the same function in base class.
– VTTNov 9 '17 at 18:11