Klasa - template dla wskaźnika

0

Witam!

Potrzebuję zrobić szablon klasy dla wskaźnika


template <typename T>
class Tmpl{

};


int main(){
    int * a = new int[5]; // cokolwiek

    Tmpl<a> tmpl;

    return 0;
}

Tak, by klasa znała adres wskaźnika, oraz jego typ np. za pomocą "typeof".

Chciałbym uniknąć takiego zapisu:


template <typename T>
class Tmpl{

public:
    Tmpl(void * addr){}

};


int main(){
    int * a = new int[5]; // cokolwiek

    Tmpl<typeof(a)> tmpl(a); // ałaaa

    return 0;
}

Jak to zrobić?

1

Użyj decltype zamiast dodatku do kompilatora. Poza tym, nie chcesz po prostu unique_ptr?

0
kq napisał(a):

Użyj decltype zamiast dodatku do kompilatora. Poza tym, nie chcesz po prostu unique_ptr?

Dzięki kq za odpowiedź.

Chcę zrobić klasę na niskopoziomowe tablice, struktury itp.
Mam cały mechanizm w C i potrzebuję go rozwinąć w C++ do dość nietypowych zastosowań.

Możesz coś więcej napisać o swoim pomyśle?

3

Wymyślasz koło na nowo. http://en.cppreference.com/w/cpp/memory/unique_ptr

Sam wydajniejszego nie zrobisz, bo to jest po prostu cieniutki wrapper nad new/delete, pozwalający jednak ich nie używać.

0
kq napisał(a):

Sam wydajniejszego nie zrobisz, bo to jest po prostu cieniutki wrapper nad new/delete, pozwalający jednak ich nie używać.

Rozwijając - nie ma różnic w wydajności pomiędzy weak_ptr, unique_ptr czy zwykłym wskaźnikiem. Drobna różnica pojawia się dopiero w shared_ptr ze względu na konstrukcje tego obiektu - musi on zliczać references counter, który jest zapewne std::atomic<long>. A tu już potrzebna synchronizacja i inne cuda.

0

Może źle wyjaśniłem problem:

struct data_t{
    char test;
};

int main(){

    struct data_t value;

    my_vector<&value> vect;

    return 0;
}

Chcę teraz w klasie utworzyć wektor typu "struct data_t", oraz najważniejsze, by konstruktor znał adres zmiennej/struktury "value".
Template nie tylko do przekazania typu, ale także adres zmiennej z którego ten typ stworzył.

0

Tylko dla zmiennych globalnych jesteś tak w stanie zrobić, ale to co chcesz nie wydaje się zbyt sensowne. Co chcesz osiągnąć?

0

http://melpon.org/wandbox/permlink/3qF2NqBqDxWvk12J
Konstrukcja nieco inna, natomiast zdaje się, że spełnia Twoje założenia.

0

Potrzebuję utworzyć wektor pewnych pól pochodzących z struktury i zapamiętać pod jakim offsetem te pole się znajduje:

#include <vector>

using namespace std;

struct data_t{
    int a;
    int b;
    int c;
};

// przyklad
template <typename T>
class my_vector
{

public:
    vector<T> _vector;
    void    * _ptr;

    my_vector(void * ptr){
        _ptr = ptr;
    }
};

#define MY_VECTOR(path, name) \
    my_vector<decltype(path)> name(&path)

int main(){

    MY_VECTOR( reinterpret_cast<struct data_t*>(0)->b, wektor);

    // wektor - wektor pól "b" struktury "struct data_t" z zapamietanym offsetem
    return 0;
}
0

Jest jedno pole b tej struktury, nie wiem jak chcesz mieć ich wektor. Jak chcesz wskazywać na to pole w wielu strukturach to po prostu trzymaj wektor struktur/wskaźników na nie.

Prawdopodobnie wymyśliłeś sobie (złe) rozwiązanie jakiegoś problemu i teraz na siłę próbujesz je zaimplementować. Opisz problem, zapewne można to lepiej rozwiązać

0
kq napisał(a):

Jest jedno pole b tej struktury, nie wiem jak chcesz mieć ich wektor. Jak chcesz wskazywać na to pole w wielu strukturach to po prostu trzymaj wektor struktur/wskaźników na nie.

Nie dopisałem po co to wszystko ;)

#define path reinterpret_cast<struct data_t*>(0)->b

my_vector< path > dataVector = getVectorData();
/**
Założenia:
1. funkcja getVectorData jest wstanie odwołać się do klasy my_vector i odczytać adres path, zapisany w _ptr
2. funkcja getVectorData zwraca stworzoną tablice która jest wypełniona danymi na podstawie adresu _ptr (ona już wie co z tym zrobić ;) )
**/
0

Nie jesteś w stanie uzależnić typu getVectorData od dataVector. Po prostu.

0

Mam dostęp do N urządzeń, które opisane są strukturą "struct data_t".
Zadanie: pobranie listy danych pól.
Najwygodniejszy zapis:

my_vector< path > dataVector = getVectorData();

Realizacja:
wymyślanie ;)

Czyli mój pomysł odpada?
Jakieś propozycje jak inaczej to zrealizować?

0

Czyli masz jakieś N globalnych instancji tej struktury i chcesz wektor ich pól b, na ten przykład?

2

std::vector<data_t> data;
i możesz
data.at(5).b
a Ty kombinujesz nie wiadomo po co.

0

Struktury nie są zadeklarowane,
Funkcja getVectorData, mając offset jest wstanie odpytać się urządzeń o te dane.

#include <iostream>
#include <vector>

using namespace std;

struct data_t{
    int p;
    int a;
    int b;
    int c;
};

// przyklad
template <typename T>
class my_vector
{

public:
    vector<T> _vector;
    void    * _ptr;

    my_vector(void * ptr = 0){
        _ptr = ptr;
    }
};


template <class T>
void getVectorData(T &vd){
    cout << "Offset: " << vd._ptr << endl; // test
    cout << "Size:   " << sizeof(vd._vector[0]) << endl; // test, potrzebny lepszy zapis
    // mamy offset oraz wielkosc, pytamy urzadzenia, mozemy budowac vektor z tymi polami
}

#define MY_VECTOR(path, name) \
    my_vector<decltype(path)> name(&path)


int main(){
    #define path reinterpret_cast<struct data_t*>(0)->b

    MY_VECTOR(path, wektor);
    // lepiej: my_vector<path> wektor;

    getVectorData(wektor);
    // lepiej: wektor = getVectorData();

    return 0;
}
0

Powiem szczerze, jestem zupełnie skołowany i niezbyt pewny co chcesz osiągnąć. Mimo wszystko wydaje mi się, że wystarczy Ci po prostu funkcja getVectorData, która dostanie odpowiednie wartości w parametrze i żaden szablon my_vector nie jest Ci do niczego potrzebny.

0

pingwindyktator

Kody które napisałem są jednym z języków którym "potrafimy" się dogadać i ukazuje problem do rozwiązania.
Nie jest to przecież finalny kod.

Temat nie jest prosty, muszę pobrać listę wybranych pól z struktury, korzystając z funkcji:

eea_read(int device, int addr, int size, void * data);

Mając strukturę danych, chcę ją w 100% wykorzystać, czyli stworzyć typ danego pola "typeof/decltype", pobrać offset "offsetof" chodź niezbyt on tutaj pasuje.

Moją wymarzoną linijką jest:

eea_vector< path > wektor = getVectorData(); // idea a nie nazwy ;)

I tak będę musiał dopisać swoją klasę, aby dopisać dodatkowe dane, np. czas odpowiedzi urządzenia itp.

Oczywiście mogę z palca podawać adres, wielkość, ale po co? szczególnie jak mam całą strukturę. Coś sie zmieni w strukturze i będę miał więcej roboty niż poprawienie samej struktury.
Jeżeli mam opierać się o strukturę, to musi wystąpić szablon w jakiejś postaci, tak by uzyskać np. wektor danych pól.

Ma być to również uniwersalna biblioteka do innych podobnych urządzeń które różnią się tylko strukturą.

0

http://melpon.org/wandbox/permlink/HxP5HIJCrdKoYNXW
może o coś takiego chodzi?

EDIT:
troche elegantsza wersja
http://melpon.org/wandbox/permlink/5ENmr8ctuMmMJLme

funkcja get_element wyciągnie Ci dowolne pole ze struktury, natomiast get_distance pozwoli okrećlić które ma być to pole. Na tej podstawie możesz stworzyć coś takiego:
http://melpon.org/wandbox/permlink/gxDAfK59QYBzsnI8

0
pingwindyktator napisał(a):

http://melpon.org/wandbox/permlink/HxP5HIJCrdKoYNXW
może o coś takiego chodzi?

EDIT:
troche elegantsza wersja
http://melpon.org/wandbox/permlink/5ENmr8ctuMmMJLme

funkcja get_element wyciągnie Ci dowolne pole ze struktury, natomiast get_distance pozwoli okrećlić które ma być to pole. Na tej podstawie możesz stworzyć coś takiego:
http://melpon.org/wandbox/permlink/gxDAfK59QYBzsnI8

Jeszcze nie widziałem ostatniego linka, bo też klepałem :)

KOD:

http://melpon.org/wandbox/permlink/EnurRaGgifqgDGjZ

W skrócie:

int main(){

    // stworzenie wektora o typie data.c.y
    my_vector<decltype(data.c.y)> wektor(&data.c.y);
    // lepiej: my_vector<data.c.y> wektor;


    // odpytanie urzadzen i pobranie danych na temat wybranego pola
    getVectorData(wektor);
    // lepiej: wektor = getVectorData();

    // przykladowy dump
    for(int i=0; i<wektor.size(); ++i){
        cout << "[" << i << "]\n";
        cout << " val: " << hex << wektor[i] << "\n";
    }

    return 0;
}

Struktury "data_t" nie można alokować bo jest duża, a potrzebne są tylko niektóre pola.
Pod pojęciem "lepiej" - to jest do czego dąże.

Moje pytania które spowodowały napisanie tego tematu to:

  1. Przekazanie wskaźnika do szablonu tak, by później odczytać adres oraz typ - po co? żeby nie pisać 2x
 my_vector<decltype(data.c.y /* 1 */ )> wektor(&data.c.y /* 2 */ );

Oraz "jawnie" nie używać decltype/typeof
2. Wywołanie funkcji która wie co zwraca, nie tylko typ a jeszcze dane

wektor = getVectorData();

pomyślałem teraz, że można przeciążyć operator =, muszę jeszcze pomyśleć.
3. Inny pomysł, ale musi być elastyczny i czytelny jak pierwotny:

my_vector<data.c.y> wektor = getVectorData();
0

http://melpon.org/wandbox/permlink/e9Vm1bh6gb6o6uTi
tutaj rozwiązanie jednego z problemów. Gdyby całość nie musiała być tak templatowa, to byłoby chyba łatwiej.

0
pingwindyktator napisał(a):

http://melpon.org/wandbox/permlink/e9Vm1bh6gb6o6uTi
tutaj rozwiązanie jednego z problemów. Gdyby całość nie musiała być tak templatowa, to byłoby chyba łatwiej.

O super jeden problem mniej i w głowie więcej, nie pomyślałem o tym ;)

Chyba jednak pomyśleć nad całkowicie innym sposobem realizacji tego wszystkiego.

Tak na podsumowanie:

  1. Czy przez templaty da się "przekazywać" tylko typy?
  2. Czy da radę przeciążyć operator = żeby uzyskać zapis:
struct cos_glupiego_t{};

struct cos_glupiego_t getVectorData(){
}

templatetralala< ... >
void operator = (T t, const struct cos_glupiego_t& foo )
{
    // dostep do klasy T - czyli my_vector<decltype(data.c.y)>
    // wpisze co chce a getVectorData jest bo sobie jest
}

/* ... */
my_vector<decltype(data.c.y)> wektor(&data.c.y);

wektor = getVectorData();

To już tak z ciekawości ;)

Więcej kombinowania niż korzyści więc będę wymyślał coś innego.

0
  1. da się przekazywać też wartości typów primitywnych, np int czy size_t
    template <size_t size> <- da sie
    template <cos_glupiego kek> <- jeśli cos_glupiego jest Twoją strukturą, to nie da się

  2. da się. Możesz przeciążyć operator jeśli jednym z jego argumentów będzie jakiś non-primitive object, czyli np Twoja własna struktura. Choć Twój operator nie wygląda dobrze, tj powinien zwracać T &. No i ten operator jeśli chce mieć dostęp do prywatnych pól to musi być zadeklarowany jako friend.

  3. w C++ nie musisz pisać struct przed nazwą obiektu struktury.
    const struct cos_glupiego_t& foo -> const cos_glupiego_t& foo

  4. sugerowałbym nie pisać tych operatorów do my_vector, tylko odwoływać się jako
    my_vector<cos> cos2; cos2._vector.cos3

Jak będą jakieś problemy to pisz, bo problem ciekawy.

0

A z templatem od funkcji można szaleć:

http://melpon.org/wandbox/permlink/iAhiTAbzLPvl2tmk

#include <iostream>

using namespace std;

struct data_t{
    int a;
    int b;
    struct{
        int x;
        struct{
            short z;
            char kredowa[15];
        }y;
    } c;
    int d;
};
// latwiejszy dostep do grzebania po strukturze, by pobrac typy oraz adresy
// nie do odczytu zapisu!!!
#define data (*reinterpret_cast<struct data_t*>(0))


template<typename T>
void foo(T a){
    cout << "addr: " << a << endl; // idzie odczytac adres
    cout << "size: " << sizeof(*a) << endl; // sprawdzic wielkosc

    __typeof__(*a) field; // stworzyc typ
    cout << "i frytki gratis: " << field.z << endl; // i przeczytac co miales w pamieci :P
}



int main(){
    foo(&data.c.y);
    return 0;
}

Czuję się oszukany przez C++ :P

0

Kilka stron zapełnione a ty cały czas implementujesz własne offsetof. Po co?

0
kq napisał(a):

Kilka stron zapełnione a ty cały czas implementujesz własne offsetof. Po co?

A gdzie?

Niby tu?

#define data (*reinterpret_cast<struct data_t*>(0))

foo(&data.c.y);
  1. offsetof daje wartość bez typu pola
  2. data.c.y <- ładne podpowiedzi daje środowisko, przy offsetof nie
0
 __typeof__(*a) field; // stworzyc typ
    cout << "i frytki gratis: " << field.z << endl; // i przeczytac co miales w pamieci :P

To nie do końca działa tak jak Ci się wydaje. W pierwszej linijce tworzysz zupełnie inny obiekt (z *a ma tylko tyle wspólnego, że ma taki sam typ). Z jakimiś tam śmieciami jako wartości.
Ale możesz przecież a->z

0
pingwindyktator napisał(a):
 __typeof__(*a) field; // stworzyc typ
    cout << "i frytki gratis: " << field.z << endl; // i przeczytac co miales w pamieci :P

To nie do końca działa tak jak Ci się wydaje. W pierwszej linijce tworzysz zupełnie inny obiekt (z *a ma tylko tyle wspólnego, że ma taki sam typ). Z jakimiś tam śmieciami jako wartości.
Ale możesz przecież a->z

Jasne, dla tego nazwałem "frytki" ;)
Dałem przykład stworzenia nowego pola, na podstawie przekazanej "typo-wartości".
A z tym "oszukany" miałem na myśli, stworzenia klasy która jest w stanie stworzyć pole o tym typie, zapamiętać wielkość i adres "typo-wartości".

Typo-wartość jest tutaj dobrym określeniem ;) Gdzie "wartość", to mam na myśli offset pola w strukturze.

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