I'm curious about the size of a very simple Demo object , so , I'm writing the following code
#include <windows.h>
#include "winrt/base.h"
#include <iostream>
#pragma comment(lib, "windowsapp")
/*
cl /nologo /await /std:c++latest /wd4002 /EHsc base_so.cpp
*/
using namespace std;
using namespace winrt;
using namespace winrt::impl;
struct IDemo;
template <typename D>
struct consume_IDemo
{
void hello();
};
template <> struct consume<IDemo> { template <typename D> using type = consume_IDemo<D>; };
template <typename D> void consume_IDemo<D>::hello()
{
WINRT_SHIM(D)->hello();
}
struct WINRT_EBO __declspec(uuid("3A44B7CC-9CB6-4512-8CAD-6400E662D865"))
IDemo : Windows::Foundation::IInspectable, consume_t<IDemo>
{
IDemo(std::nullptr_t = nullptr) noexcept {};
};
template <> struct abi<IDemo>
{
struct type : IInspectable
{
virtual HRESULT hello() = 0;
};
};
template <typename D>
struct produce<D,IDemo> : produce_base<D,IDemo>
{
HRESULT hello() override
{
shim().hello();
return S_OK;
}
};
struct Demo : implements<Demo,IDemo>
{
Demo()
{
cout << "sizeof Demo 0x" << hex << sizeof(*this) << dec << endl;
cout << "sizeof m_references 0x" << hex << sizeof(std::atomic<std::conditional_t<1, uintptr_t, uint32_t>>) << dec << endl;
cout << "is_composing " << is_composing << endl;
cout << "outer " << outer() << endl;
}
HRESULT hello()
{
cout << __FUNCTION__ << endl;
return S_OK;
}
};
int main()
{
Demo d;
}
and the output is
sizeof Demo 0x18
sizeof m_references 0x8
is_composing 0
outer 0000000000000000
I think the sizeof Demo should be 0x10 (64 machine) : sizeof(m_references)+sizeof(produce<Demo,IDemo>) , so , what is the extra 8 bytes ? many thanks!
It's either padding or v-tables. Maybe both...
The compiler is likely to insert a v-table pointer for each base class that has at least one virtual method declared. (And as an aside, when you do a C-cast, static_cast, or dynamic_cast from the concrete class to the non-first base class, the compiler will change the pointer value to that of the base-class or its v-table.)
Let's break it down.
Demo
inherits from implements<Demo,IDemo>
implements
is defined as follows:
struct implements : impl::producers<D, I...>, impl::base_implements<D, I...>::type
{
Now we're getting into WinRT noise. But it does seem to suggest multiple-inheritance. But it's just easier to break this out it the debugger.... There you go. The first vtable is for IUnknown. The other is something related to IInspectable.
So it makes sense. Each v-table is an 8 byte pointer. And the m_references is also 8 bytes. 8+8+8 = 24 = 0x18