Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

C++ i tworzenie zmiennej typu na podstawie jego nazwy

Ostatnio zmodyfikowano 2014-08-18 14:48
Autor Wiadomość
An0nym8us
Temat założony przez niniejszego użytkownika
C++ i tworzenie zmiennej typu na podstawie jego nazwy
» 2014-08-15 23:29:15
Witam ponownie :).

Mam kolejny problem, ale uznałem że nie będę o nim pisał w poprzednim temacie, tylko utworzę nowy.

Nawiązując do poprzedniego tematu, jak niektórym wiadomo mam enum DataType, dzięki któremu program ma określone, jaką strukturę posiada nadesłany pakiet. Problem w tym, że niezbyt jest to bezpośrednie rozwiązanie problemu, bo musiałbym stworzyć switch...case i obsłużyć każdy rodzaj danych. Niby nie jest to aż tak męczące, bo specjalnie dostosowałem wartości w enumie tak, aby łatwo było ustalić czy dany typ to tablica, czy jest unsigned czy posiada obie te cechy, ale jednak wolałbym się dowiedzieć czy jest jakieś bardziej "ekonomiczne" rozwiązanie.

Więc, czy jest możliwe zamienienie nazwy klasy/typu na tę klasę/typ? Czytałem, że nie bo w C++ nie ma Reflection. Wpadłem natomiast na inny pomysł: stworzenie unordered_map, w której to klucz byłby typu DataType, a wartość byłaby "typu" class (jak w szablonach) - niestety to nie działa (i nawet mnie to nie dziwi). W każdym bądź - czy mogę w miarę prosto zaimplementować tego typu rozwiązanie, czy raczej polecacie napisać ten switch...case i mieć spokój? Pozdrawiam.
P-115553
Jacob99
» 2014-08-16 10:55:07
czy jest możliwe zamienienie nazwy klasy/typu na tę klasę/typ?
 Co dokładnie masz na myśli?
P-115560
pekfos
» 2014-08-16 12:06:37
Nie da się. Typy są kontrolowane w czasie kompilacji. Możesz to obejść tworząc typ przechowujący wartość jednego z wielu typów, ale zastanów 2 razy czy tego naprawdę potrzebujesz i 20 razy, zanim zapytasz, jak to osiągnąć.. W gruncie rzeczy nie powinieneś potrzebować takich obejść.
P-115567
Monika90
» 2014-08-16 12:52:00
Java ma Reflection, a C++ nie. Ale jeżeli można zrobić to co chcesz w Javie, to można i w C++.

Można np. zrobić tablicę wskaźników do funkcji interpretujących dane

enum DataType : unsigned char
{
    Bool = 0x01, Byte = 0x02, Short = 0x03, Long = 0x05
};

struct DataTypeHash
{
    //
trzeba zdefiniować hash dla enuma, w C++14 to już nie będzie potrzebne
};

void handle_bool(const void*) { }
void handle_byte(const void*) { }
void handle_short(const void*) { }
void handle_long(const void*) { }

std::unordered_map<DataType, void (*)(const void*), DataTypeHash> handlers =
    {{Bool, handle_bool}, {Byte, handle_byte},
    {Short, handle_short}, {Long, handle_long}};


I teraz jeżeli type to typ danych, a data to wskaźnik do danych, to wywołać właściwą funkcję obsługi można tak:
handlers[type](data);
(pomijam sprawdzanie błędów)

Ale to są funkcje globalne, które działają w środowisku globalnym, coś lokalnego byłoby lepsze. Więc może tablica wkaźników do funkcji składowych:

class Handler
{
public:
    void handle_bool(const void*) { }
    void handle_byte(const void*) { }
    void handle_short(const void*) { }
    void handle_long(const void*) { }
};

std::unordered_map<DataType, void (Handler::*)(const void*), DataTypeHash> handlers =
    {{Bool, &Handler::handle_bool}, {Byte, &Handler::handle_byte},
    {Short, &Handler::handle_short}, {Long, &Handler::handle_long}};
   
Handler h;
(h.*handlers[type])(data);


a może tablica std::function<>, to chyba najbardziej ogólne podejście

std::unordered_map<DataType, std::function<void (const void*)>, DataTypeHash> handlers;

P-115568
An0nym8us
Temat założony przez niniejszego użytkownika
» 2014-08-18 14:11:51
Postanowiłem dać sobie 2 dni przerwy (ot taki reset :D), dzisiaj będę nad tym pracował. Tak szczerze powiedziawszy to trochę może i roboty będzie ze switch... case (niekoniecznie roboty, chciałem uniknąć monotonii w kodzie, bo w każdym "case" będzie się zmieniać tylko typ danych (no i kod trzeba pośrednio to tego dostosować), reszta kodu bez zmian), ale wydaje mi się że więcej byłoby z wprowadzeniem "Reflection".

Trochę się zamotałem teraz: czy posiadając wskaźnik void* mogę "wyciągnąć" przynajmniej jaką długość w bajtach ma zmienna na którą on wskazuje?
P-115669
pekfos
» 2014-08-18 14:48:01
Trochę się zamotałem teraz: czy posiadając wskaźnik void* mogę "wyciągnąć" przynajmniej jaką długość w bajtach ma zmienna na którą on wskazuje?
Nie.
P-115679
« 1 »
  Strona 1 z 1