[C++] Nietypowa konstrukcja a przenośność kodu.

0

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::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ć.

0

To, co opisujesz bardzo przypomina implementację list powiązanych w Linuksie.

Opis (szczególnie interesująca jest część How Does This Work?):
http://isis.poly.edu/kulesh/stuff/src/klist/

Linux jest na kilkudziesięciu platformach i na wszystkich to działa bez problemu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1