Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    [c++]programmazione generica

    Ciao.
    Sto leggendo effective stl di scott mayer.
    Mi è venuto un dubbio:
    nella programmazione generica come strutturo le classi?
    voglio dire invece dei classici cicli posso usare i function object dell' stl , ma dove metto li metto?
    Di operator () deve essercene uno per classe?

    struct mycmp {
    bool operator () (const pair<int,giugio*>& a, const pair<int,giugio*>& b) {
    return a.first < b.first;
    }
    };

    quindi per ogni funzionalità devo creare una classe diversa?
    Come mai?
    non sarebbe meglio inserire tutte le funzionalità che puo' avere un oggetto nella rispettiva classe?
    capisco che cosi' se voglio usare una funzionalità per un altra classe devo instanziare una classe che non centra niente ...
    insomma sono un po confuso

  2. #2
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    Per esempio , un caso concreto:
    Ho una serie di classi di oggetti per architettura :
    1)muri
    2)colonne
    3)pilastri
    4)solai
    ciascuno di queste classi ha una polilinea , un insieme di punti che descrivono l'oggetto che devo importare.
    Ogni punto è un insieme di float ,3 per precisione:x,y e z.
    A seconda del parametro di rotazione devo poter ruotare tutti i punti della polilinea.

    Ho pensato di creare un function object che prende come parametri i tre assi e ruota la polilinea.
    questa funzionalità è esattamente identica per tutti e 4 gli elementi,

    senza programmazione generica si puo' fare ereditare tutti questi elementi da una classe comune base in cui implementare la funzione di rotazione dei punti.

    Con un function object penso basti definirlo e preso il container stl che contiene i punti con un for_each richiamare il function object e non sono piu vincolato da nessun tipo di ereditarietà oltre a poter usare range iteratori ecc..., è questo un vantaggio?

    ma dove scrivo fisicamente il function object in un progetto ?
    in un file con una classe per functore?

    shodan mi ha piu volte detto che non sono due programmazioni una alternativa all altra e che il saper utilizzare a volte l'una a volte l'altra è il punto.

    ma voi in questo caso concreto cosa utilizzereste e perchè?

    ps. scusate se mi ripeto a volte , ma voglio capire .
    grazie per la sopportazione.
    ciao

  3. #3
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Tieni sempre presente che un functor riceve un tipo specifico, quindi se i muri, colonne (etc) non hanno una comune classe base, sei costretto quantomeno a scrivere diversi operatori() (uno per tipo), o ricorrere a una funzione template.

    Quando dico che i due tipi di programmazione sono complementari, mi riferisco a:
    codice:
    class Base{};
    
    vector<base*>
    list<base*>
    deque<base*>
    std::array<base*>
    shared_prtr<base>
    Sono tutti template (quindi generici), ma ospitano un tipo polimorfo. Le due tipologie si integrano.

    Venendo al tuo problema.
    E' scontato che ci debbano essere dei vincoli. Il codice di rotazione dev'essere lo stesso per ogni oggetto non polimorfo che passi al functor, se solo uno di essi richiede codice aggiuntivo, si perde in genericità.
    Altresi è scontato che i container di provenienza di questi oggetti debbano essere diversi.
    Detto questo, il codice del functor (quello dentro l'operatore () per capirsi) puoi scriverlo anche in un file cpp, però i tipi devono essere esplicitati.
    codice:
    // file .h
    struct RotateFunctor {
        ReturnType1 operator()(const muro& t);
        ReturnType2 operator()(const colonna& t);
        ReturnType3 operator()(const pilastri& t);
        ReturnType4 operator()(const solai& t);
    };
    
    // file .cpp
    ReturnType1 RotateFunctor::operator()(const muro& t) { ... }
    ReturnType2 RotateFunctor::operator()(const colonna& t) { ... }
    ReturnType3 RotateFunctor::operator()(const pilastri& t) { ... }
    ReturnType4 RotateFunctor::operator()(const solai& t) { ... }
    Il problema è che se devi aggiungere dei tipi, devi rimettere mano alla classe. Un approccio un pò pesante per la manutenzione.

    Come soluzione si può pensare a un functor con funzione template. Si guadagna in genericità, ma va tutto nel file.h.
    codice:
    struct RotateFunctor {
        template <typename T>
        ReturnType1 operator()(const T& t) { ... }
    };
    Il vincolo però è che il codice nella funzione template è lo stesso per tutti i tipi.

    La terza soluzione (forse la migliore dal mio punto di vista) è sfruttare la specializzazione dei template.
    codice:
    template <typename T>
    struct RotateFunctor {
        ReturnType1 operator()(const T& t) { ... }
    };
    
    template <>
    struct RotateFunctor <muri> {
        ReturnType1 operator()(const muri& t) { ... }
    };
    
    template <>
    struct RotateFunctor <colonne> {
        ReturnType1 operator()(const colonne& t) { ... }
    };
    // etc.
    A compile time, il compilatore richiamerà la specializzazione corretta e la userà nell'algoritmo di rotazione. Nel functor specializzato, inoltre si può inserire codice specifico per singola classem si possono anche aggiungere funzioni solo in quel functor specializzato etc.
    Le implementazioni possono essere inserite in un file cpp (bisogna però vedere se ne vale la pena), e lasciare solo i prototipi dei functor specializzati nel file .h (insieme a tutto il template generico ovviamente).
    Se ti serve aggiungere un functor specifico, basta specializzare quello generico e ricompilare il programma, senza modificare altro codice.
    Dulcis in fundo, puoi anche costringere a dover specificare il template.
    codice:
    template <typename T>
    struct RotateFunctor;
    Se si tenta di usare il functor non specializzato, si avrà errore di compilazione.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie Shodan.
    Ho letto con attenzione il tuo post e ho capito , anche aiutandomi coi libri.
    Quello che ti chiedevo è che una polilinea è un insieme di punti 2d , due double o 3d 3 double.
    In ogni classe muro,solaio,beam o column ho un container stl che contiene dei dati di una polilinea , 2DPoint o 3Dpoint che a loro volta contengono dei double, 2 o 3.
    Non basta scrivere un functore che utilizza dei 2DPoint o 3Dpoint e passargli la matrice di rotazione?
    questo andrebbe genericamente applicato a tutte le classi che derivano da IfcBase(la classe padre dei vari elementi beam,column ecc...)con un template come hai scritto tu.

    Ora , se è una cosa plausibile e buona (dimmi tu se percaso è una sciocchezza) dove inserisco questo function object?
    dovrà "stare fuori" dalle classi Degli elementi , in quanto deve essere pubblica a tutte queste classi, e basterà scriverla una volta per tutte , anche in futuro , se avro un nuovo elemento con una polilinea basterà richiamarla(con un for_each sul container slt) in quanto contiene dei double alla fine.

    forse piu' si mantiene un astrazione e meno si creano dei vincoli come ad es gerarchie di derivazione complesse , piu' si puo generalizzare il codice e riutilizzarlo , puo essere?
    ciao.
    Grazie.

  5. #5
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Mi sfugge cosa intendi con "matrice di rotazione". Ma se devi passare ulteriori parametri al functor, puoi usare il costruttore. Il functor è pur sempre una classe, no? L'unico vincolo è che è obbligatorio avere operator(), il resto è libero.

    questo andrebbe genericamente applicato a tutte le classi che derivano da IfcBase
    Non vedo cosa c'entri. Se al functor passi un 2DPoint o un 3DPoint, lui si limita a elaborare quel dato senza sapere da dove provenga.

    dovrà "stare fuori" dalle classi Degli elementi
    Questa non l'ho capita. :master:

    forse piu' si mantiene...
    Senza forse.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  6. #6
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    Originariamente inviato da shodan
    Mi sfugge cosa intendi con "matrice di rotazione". Ma se devi passare ulteriori parametri al functor, puoi usare il costruttore. Il functor è pur sempre una classe, no? L'unico vincolo è che è obbligatorio avere operator(), il resto è libero.
    ok, capito,
    si , per matrice di rotazione intendo un parametro per cui va moltiplicato ciascun punto per essere ruotato , è una roba di algebra matriciale e trigonometria per intenderci.

    Non vedo cosa c'entri. Se al functor passi un 2DPoint o un 3DPoint, lui si limita a elaborare quel dato senza sapere da dove provenga.
    una mia sciocchezza.

    Questa non l'ho capita. :master:
    intendevo se devo creare per ogni function object una classe a parte e "metterla" all esterno delle altre classi o se si puo inserire il function object all interno ad es della classe muro, ma ho gia capito , se la metto nella classe muro verra usata solo da muro , non ha senso , altra sciocchezza

    Senza forse.
    ok.


    ciao.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.