amosk
amosk

Reputation: 385

Detect if inherited function is overridden

I came up with the following code detecting at compile time if inherited functions are overridden in the derived class. It works with all major compilers - gcc/clang/msvc. But is this approach actually backed by the standard?

#include <type_traits>

struct B {
    virtual void f1() {}
    virtual void f2() {}
    void f3() {}
    void f4() {}
};

struct D: B {
    void f1() override {}
    void f3() {}
};

int main()
{
    static_assert(!std::is_same_v<decltype(&B::f1), decltype(&D::f1)>, "overriden");
    static_assert(std::is_same_v<decltype(&B::f2), decltype(&D::f2)>, "base");
    static_assert(!std::is_same_v<decltype(&B::f3), decltype(&D::f3)>, "overriden");
    static_assert(std::is_same_v<decltype(&B::f4), decltype(&D::f4)>, "base");
    return 0;
}

Upvotes: 11

Views: 366

Answers (1)

Peter
Peter

Reputation: 3135

Found it, this is covered by by section 20.15.9 Member relationships, point 5 of the standard:

Note: The type of a pointer-to-member expression &C::b is not always a pointer to member of C, leading to potentially surprising results when using these functions in conjunction with inheritance.

Given example:

struct A { int a; };
struct B { int b; };
struct C: public A, public B { };

// The following will succeed because, despite its appearance,
// &C::b has type "pointer to member of B of type int"
static_assert(is_pointer_interconvertible_with_class( &C::b ));

And so on and so forth. That explain why in your example, &B::f2 and &D::f2 as well as &B::f4 and &D::f4 have the same type void(B::*)().

Upvotes: 7

Related Questions