Virtual inheritance and class function pointer size

139 Views Asked by At

I have the following code, I am using MSVC:

template <typename T>
void CanMock() {
  class SimpleType {};
  static_assert(sizeof(void(SimpleType::*)()) == sizeof(void(T::*)()),
                "Can't mock a type with multiple inheritance or with "
                "non-polymorphic base class");
}

int main() {
  class base {};
  class derived : public base {};
  class derivedVirtual : virtual public base {};
  CanMock<derived>();
  CanMock<derivedVirtual>();
}

The static_assert in CanMock passes when called with derived but fails when called with derivedVirtual.

As far as I understand the assertion tries to compare the size of the class function pointer of a SimpleType with the size the class function pointer of derivedVirtual,

Now my questions are:

  • I understand that the size of a derivedVirtual should increase because of the vtable pointer stored in it (right?), but why does the size of derivedVirtual class function pointer increases when inheriting with virtual?
  • Why in clang the same assertion does not fail?

Just to give a little more context:

I am using FakeIt for testing. At some point I wanted to Mock a specific class, but I was not able due to the failing static_assert inside FakeIt source code. After some investigation I understood that the failure was due to the fact that the class that I was trying to mock was inheriting virtually from a base class. So I came with the above code, copy-pasted from FakeIt.

Here is the line where I copied from.

So another question that came to my mind is: which is the correlation between virtual inheritance and the ability to mock a class?

Thank you for your time.


Edit:

Here is the TEST_CASE that does not compile when I try to Mock the class:

TEST_CASE("Mock") {
    struct base {};
    struct derivedVirtual : virtual public base {
        virtual int A() = 0;
    };
    fakeit::Mock<derivedVirtual> mock; // This triggers the failing static_assert in MSVC but compiles in Clang
}

Is there a workaround to allow me to mock the class with FakeIt?

0

There are 0 best solutions below