Chcę napisać pewną biblioteczkę która ma być przenośna na różne platformy i kompilatory C++. Opiera się ona na mechanizmie który przedstawiłem poniżej.
Jest klasa Foo, zawiera sub-klasę Foo::Action oraz pole action tej klasy (klasa Foo::Action jest przeznaczona tylko dla pola action).
Celem mechanizmu jest z poziomu klasy Foo::Action wydobycie adresu obiektu Foo (do którego należy dany obiekt Foo::Action) bez wcześniejszego zapamiętania tego adresu gdzieś w pamięci.
Inaczej mówiąc - mając adres obiektu Foo z łatwością można obliczyć adres należącego do niego obiektu Foo::Action np.
Foo::Action* Foo::GetAddressOfAction() { return &this->action; }
Natomiast ja chcę ten proces odwrócić:Foo* Foo::Action::GetAddressOfFoo() { return /* ... */; }
Dokładniej sprecyzowany cel zakłada poprawność wykonania tego co opisałem wewnątrz funkcji main(). A oto kod:
```cpp
#include <stddef.h>
#define cpp_offsetof(s, m) (((size_t)&reinterpret_cast<const volatile char&>((((s*)(char*)8)->m))) - 8)
struct Foo : /* dowolna baza */
{
/* ... */
void DoAction() { /* ... */ }
struct Action /* klasa użyta jedynie dla pola "action" */
{
Foo *GetFoo() { return reinterpret_cast<Foo*>((ptrdiff_t)this - cpp_offsetof(Foo, action)); }
void Do() { GetFoo()->DoAction(); }
}
action;
/* ... */
};
struct Bar : /* dowolnie dziedziczy po Foo (pośrednio, wirtualnie ...) */
{
/* ... */
};
int main()
{
Bar bar;
bar.action.Do(); // docelowa ma wywołać "dynamic_cast<Foo&>(bar).DoAction()"
return 0;
}
Szukam ewentualnych pułapek.
Po mojej analizie jestem dość mocno przekonany o ich braku z jednym wyjątkiem. Jedyne czego nie jestem pewien to czy będzie działać pobranie adresu do obiektu action wewnątrz definicji klasy tego obiektu. Co o tym sądzicie? Testowałem kod na różnych kompilatorach (Bornalnd C++, Digital Mars, GCC, Open Watcom, Visual C++) z wyłączonymi rozszerzeniami i żaden się nie pluł.
Czy dostrzegacie jeszcze jakieś inne pułapki?
Aha, jeszcze jedno. Założenie jest takie, że adres 0x08 jest poprawnym adresem obiektu w pamięci (makro cpp_offsetof) i na ten temat już nie chcę rozwodzić. Zresztą to makro pochodzi z projektu w którym ów biblioteczki chcę użyć.