Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2005
    Messaggi
    117

    [C++] differenziazioni template

    scrivo un classe template, vorrei sapere se è possibile scrivere metodi differenziati a seconda del tipo che gli passo:

    cioè per un'istanza <int> voglio un metodo, per un'istanza <float> lo stesso metodo deve agire in modo leggermente diverso. si può fare? come?

  2. #2
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    Si è possibile, l'argomento è noto come template specialization .
    Fai conto di avere questo template di classe:

    template <typename T>
    class Stack{
    ...
    };


    Ad esempio lo puoi specializzare per le stringhe:

    template<>
    class Stack<std::string> {
    ...
    };


    Ovviamente poi ogni sua funzione deve riportare esplicitamente il tipo di dato che stai specializzando. Ad esempio...

    std::string Stack<std::string>:op(){
    ...
    }




    La specializzazione può anche essere parziale. Ad esempio data
    template <typename T1, typename T2>
    class MyClass{
    ...
    };


    ...sono possibili (ad es.) i seguenti tipi di specializzazione parziale:

    //Entrambi i parametri sono dello stesso tipo
    template <typename T>
    class MyClass<T, T>{
    };



    //Il secondo parametro è un tipo (gia) noto
    template <typename T>
    class MyClass<T, int> {
    };



    //Entrambi i parametri sono puntatori, non necessariamente dello stesso tipo
    template <typename T1, typename T2>
    class MyClass<T1 *, T2 *>{
    };



    Dati poi i seguenti input...

    MyClass<int, float>; //Invoca MyClass<T1, T2>
    MyClass<float, float>; //Invoca MyClass<T, T>
    MyClass<float, int>; //Invoca MyClass<T, int>
    MyClass<int *, float *>; //Invoca MyClass<T1*, T2*>

    Problemi possono sorgere qualora più specializzazioni parziali soddisfino allo stesso modo una chiamata. In questo caso la chiamata è ambigua e si riceve un errore.

    MyClass<int, int>; //ERROR: invoca sia MyClass<T, T> che MyClass<T, int>
    MyClass<int *,int *>; //ERROR: invoca sia MyClass<T,T> che MyClass<T1 *, T2 *>


    La seconda può ad esempio essere risolta con un'altr specializzazione parziale.
    template <typename T>
    class MyClass<T *, T *>{
    };



    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2005
    Messaggi
    117
    guarda il seguente listato:

    codice:
    #include <iostream.h>
    
    template <typename Tipo>
    struct nodo {
    	Tipo val;
    	struct nodo <Tipo> *next;
    };
    
    template <typename Tip>
    class Lista
    {
    	struct nodo <Tip> *l;
    	int lunghezza;
    	
    	public:
    		Lista()
    		{
    			l = NULL;
    			lunghezza = 0;
    		}
    		
    		void push(Tip el)
    		{
    			struct nodo <Tip> *z = new(struct nodo <Tip>);
    			z->val = el;
    			z->next = l;
    			l = z;
    			lunghezza++;
    		}
    
    		void visualizza(void)
    		{
    			struct nodo <Tip> *z = l;
    			while (z != NULL)
    			{
    				cout << z->val << " ---> ";
    				z = z->next;
    			}
    			cout << "NULL\n\n";
    		}
    		
    		int lung(void)
    		{
    			return lunghezza;
    		}
    };
    
    int main()
    {
    	Lista <char [20]> lis;
    	lis.push("cioa");
    	lis.push("come");
    	lis.visualizza();
    	cout << lis.lung();
    }
    
    template<>
    Lista<char *>::void push(char *s){ 
    	for (int = 0; (l->val[i] = s[i]) != '\0'; i++)
    		;
    	lunghezza++;
    }
    cosa c'è ke non va?

  4. #4
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    template<>
    Lista<char *>::void push(char *s){
    for (int = 0; (l->val[i] = s[i]) != '\0'; i++)
    ;
    lunghezza++;
    }


    Qui ci sono diversi errori.
    Lista<char *>::void push(char *s) //void va davanti

    for(int = 0; //int ... cosa?

    l->val[i] //l nn è dichiarato
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

  5. #5
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    p.s. ed in ogni caso per fare la specializzazione devi ridefinire completamente la classe specializzata.


    edit: per capirci...
    template<>
    class Lista<tipo di dato> {
    //ridefinizione dei membri, delle funzioni
    };
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

  6. #6
    Utente di HTML.it
    Registrato dal
    Jun 2005
    Messaggi
    117
    devo riscrivere tutta la classe con tutte le funzioni? oppure riscrivere la classa con solo quella funzione?

    mi potresti scrivere il listato per fare una cosa del genere come la voglio fare io?

  7. #7
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    devi riscrivere la classe indicando esplicitamente il tipo che stai specializzando e reimplementare le funzioni che ovviamente puoi modificare.
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

  8. #8
    Utente di HTML.it
    Registrato dal
    Jun 2005
    Messaggi
    117
    così?

    codice:
    #include <iostream.h>
    
    template <typename Tipo>
    struct nodo {
    	Tipo val;
    	struct nodo <Tipo> *next;
    };
    
    template <typename Tip>
    class Lista
    {
    	struct nodo <Tip> *l;
    	int lunghezza;
    	
    	public:
    		Lista()
    		{
    			l = NULL;
    			lunghezza = 0;
    		}
    		
    		void push(Tip el)
    		{
    			struct nodo <Tip> *z = new(struct nodo <Tip>);
    			z->val = el;
    			z->next = l;
    			l = z;
    			lunghezza++;
    		}
    
    		void visualizza(void)
    		{
    			struct nodo <Tip> *z = l;
    			while (z != NULL)
    			{
    				cout << z->val << " ---> ";
    				z = z->next;
    			}
    			cout << "NULL\n\n";
    		}
    		
    		int lung(void)
    		{
    			return lunghezza;
    		}
    };
    
    template<>
    class Lista<char *>{
    	struct nodo <char *> *l;
    	int lunghezza;
    	
    	public:
    		void push(char *s){ 
    			for (int i = 0; (l->val[i] = s[i]) != '\0'; i++)
    				;
    			lunghezza++;
    		}
    };
    
    
    int main()
    {
    	Lista <char [20]> lis;
    	lis.push("cioa");
    	lis.push("come");
    	lis.visualizza();
    	cout << lis.lung();
    }
    nemmeno mi va...

  9. #9
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    ti posto il codice completo dell'esempio che ti ho fatto dai miei appunti


    #ifndef _mystack
    #define _mystack

    #include <stdexcept>
    #include <vector>

    template <typename T>
    class Stack{

    private:

    std::vector<T> elems;

    public:

    inline bool empty() const{ return elems.empty(); }
    T pop();
    void push(T const&);
    T top() const;
    };


    template <typename T>
    void Stack<T>:ush(T const& elem){

    elems.push_back(elem);
    }


    template<typename T>
    T Stack<T>:op(){

    if(elems.empty())
    throw std:ut_of_range("Stack<>:op(): empty stack");

    else{
    T elem = elems.back();
    elems.pop_back();
    return elem;
    }
    }


    template<typename T>
    T Stack<T>::top() const{

    if(elems.empty())
    throw std:ut_of_range("Stack<>::top(): empty stack");

    return elems.back();
    }


    //Specializzazione stringhe

    template<>
    class Stack<std::string> {

    private:
    std::vector<std::string> elems;

    public:
    inline bool empty() const{ return elems.empty(); }
    void push(std::string const&);
    std::string pop();
    std::string top() const;
    };


    void Stack<std::string>:ush(std::string const& elem){
    elems.push_back(elem);
    }


    std::string Stack<std::string>:op(){

    if(elems.empty())
    throw std:ut_of_range("Stack<std::string>:op(): empty stack");
    else{
    std::string temp = elems.back();
    elems.pop_back();
    return temp;
    }
    }


    std::string Stack<std::string>::top() const{

    if(elems.empty())
    throw std:ut_of_range("Stack<std::string>::top(): empty stack");

    return elems.back();
    }

    #endif
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

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.