What I am trying to do is to have a class which is aware of its offset within an enclosing class with no runtime overhead at all. Here's an example of what I wish I could do:
template<int offset>
struct Inner {
};
struct Outer {
   int placeholder;
   Inner<offsetof(Outer, ptr)> ptr; 
};
The above code doesn't compile because offsetof(Outer, ptr) doesn't know about ptr (it's helping define it). I have implemented a few versions of this same idea that do incur runtime overheads (both in memory and executed instructions), but I'm having trouble implementing a "0 runtime overhead" version like my dream implementation above. Any ideas how this can be done?
The hard thing is figuring out a way for the outer type to automate production of the inner offsets, without having to write each one by hand. Doing it by hand is easy, but tedious, eg.
// use an enum to create distinct types
template<typename Outer, typename Outer::FieldId ID>
struct Inner
{
    static constexpr size_t offset();
};
struct Outer
{
    enum FieldId { First, Second };
    int header;
    Inner<Outer, FieldId::First> first;
    double interstitial;
    Inner<Outer, FieldId::Second> second;
    static constexpr size_t offset_of(std::integral_constant<FieldId, FieldId::First>) { return offsetof(Outer, first); }
    static constexpr size_t offset_of(std::integral_constant<FieldId, FieldId::Second>) { return offsetof(Outer, second); }
};
template<typename Outer, typename Outer::FieldId ID>
constexpr size_t Inner<Outer, ID>::offset()
{
    return Outer::offset_of(std::integral_constant<decltype(ID), ID> {});
}
This is clunky, partly because of the std::integral_constant wrapper (which could be avoided or typedef'd), but mostly because the ID-to-field mapping has to be expressed manually in code.
Automating production is hard without compile-time reflection. You can automate everything if you just use a tuple-like object instead of a struct at the top level, but that makes it harder to interleave "smart" and dumb members, and probably changes the layout, and it definitely breaks the StandardLayoutType requirements, which may prevent offsetof from working entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With