Witam.
Mam klasę szablonową typu variadic
z jedną specjalizacją:
template<typename... T>
struct Base
{
int X;
};
template<typename First, typename... Rest>
struct Base<First, Rest...> : public First, public Base<Rest...>
{
};
Całość działa tak, że pusta klasa Base
(ta ze specjalizacją) dziedziczy rekursywnie po wszystkich elementach, a na samym końcu (gdy zostaje już tylko jeden element) dziedziczy sama po sobie, ale w wersji podstawowej (tej z zawartością):
struct Base : public First, public Base<>
{
};
Dodatkowo używam takiego modelu, by korzystać ze static_assert()
dla każdego First
i sprawdzać, czy wskazany typ spełnia odpowiednie kryteria (tutaj to pominąłem, żeby nie zaśmiecać kodu). Poniżej przykładowe klasy wsadowe:
struct Addon1
{
int Value1;
};
struct Addon2
{
int Value2;
};
Sęk w tym, że chciałbym potem przetrzymywać takie klasy w kontenerze wskaźników (np. std::vector
) i używając dowcastów
i upcastów
dokopywać się do składników bazowych. Niestety nie mogę sobie poradzić z odpowiednim rzutowaniem:
Base<Addon1, Addon2> B;
B.X = 123;
B.Value1 = 10;
B.Value2 = 20;
Base<>* BasePtr = &B;
std::cout << BasePtr->X << std::endl; //Wyświetla 123 = OK
std::cout << reinterpret_cast<Addon2*>(BasePtr)->Value2 << std::endl; //Wyświetla 123 = błąd, powinno być 20
void* AnyPtr = &B;
std::cout << reinterpret_cast<Base<>*>(AnyPtr)->X << std::endl; //Wyświetla 10 = błąd, powinno być 123
std::cout << reinterpret_cast<Addon2*>(AnyPtr)->Value2 << std::endl; //Wyświetla 10 = błąd, powinno być 20
A co konkretnie próbuję osiągnąć? Mam klasę SpriteEx<>
, która może zostać rozbudowana o dodatkowe efekty, np. SpriteEx<Saturation, Contrast>
. Dzięki modułowości klasa jest lżejsza, co przy setkach czy nawet tysiącach instancji jednocześnie przechowywanych w pamięci ma znaczenie, zwłaszcza, że wszystkich efektów jest ponad 50, a każdy z nich dodaje od jednego do kilku floatów
, przy czym gotowy Sprite
średnio korzysta tylko z 0-3 efektów naraz. Takie gotowe Sprite'y
chcę przechowywać na liście, by klasa renderująca mogła przelecieć ją w pętli i w zależności od specjalnych flag rozpoznać jakie rozszerzenia (efekty) wchodzą w skład klasy i je zastosować (narysować), używając rzutowania.
Ktoś mógłby podpowiedzieć, co robię źle i jak to powinienem rozwiązać?