Dubbi sull'uso di typename in C++

di il
2 risposte

Dubbi sull'uso di typename in C++

Salve ragazzi, sono nuovo con la programmazione ad oggetti e soppratutto non riesco a stare dietro ad un mio prof che da troppe cose per scontate.
Questo prof ci ha mostrato (velocemente e male) come creare una classe astratta "LinearList" e successivamente specializzarla creando un'altra classe che utilizza i vettori come rappresentazione della lista. Fin qui tutto bene, il punto è che non ho capito bene l'utilizzo della parola typename.
So che sarà un dubbio stupido ma non sono riuscito a venirne a capo da solo.

La classe astratta è questa:

template<class T, class P>
class LinearList {
 public:
	typedef T value_type; //alias, rinomino il tipo generico T
	typedef P position; //alias, rinomino il tipo generico P

	//Metodi virtuali
	virtual void create() = 0;
	virtual bool empty() const = 0;
	virtual value_type read(position p) const = 0;
	virtual void write(const value_type &elemento, position p) = 0;
	virtual position begin() const = 0;
	virtual bool end(position p) const = 0;
	virtual position next(position) const = 0;
	virtual position previous(position) const = 0;
	virtual void insert(const value_type &x, position p) = 0;
	virtual void erase(position p) = 0;

};
La specializzazione invece è questa:


template<class T>
class ListVector : public LinearList<T, int> {

public:
	typedef typename LinearList<T, int>::value_type value_type;
	typedef typename LinearList<T, int>::position position;

	//Costruttori e Distruttore
	ListVector();
	ListVector(int dimensione);
	ListVector(const ListVector<T>& altro);
	~ListVector();

	//Diamo una realizzazione ai metodi virtuali presenti nella classe astratta LinearList
	void create();
	bool empty() const;
	value_type read(position p) const;
	void write(const value_type &elemento, position p);
	position begin() const;
	bool end(position p) const;
	position next(position p) const;
	position previous(position p) const;
	void insert(const value_type &x, position p);
	void erase(position p);

private:
	int lunghezza;
	int dimensioneArray;
	value_type* elementi;
	void cambiaDimensione(T*& array, int vecchiaDimensione, int nuovaDimensione);
};



template<class T>
ListVector<T>::ListVector(){

	dimensioneArray = 10;
	this->create();
}


template<class T>
ListVector<T>::ListVector(int dimensione){

	dimensioneArray = dimensione;
	this->create();
}


template<class T>
ListVector<T>::ListVector(const ListVector<T>& altro){

	this->dimensioneArray = altro.dimensioneArray;
	this->lunghezza = altro.lunghezza;
	this->elementi = new T[dimensioneArray];
	for(int i=0; i<dimensioneArray; i++)
		this->elementi[i] = altro.elementi[i];
}


template<class T>
ListVector<T>::~ListVector(){

	delete elementi;
}


template<class T>
void ListVector<T>::create(){

	this->elementi = new T[dimensioneArray];
	this->lunghezza = 0;
}


template<class T>
bool ListVector<T>::empty() const{

	return(lunghezza == 0);
}


//Nel caso non è rispettata la precondizione che ritorna??
template<class T>
typename ListVector<T>::value_type ListVector<T>::read(position p) const{

	if((p > 0) && (p < lunghezza + 1))
		return(elementi[p-1]);
}


template<class T>
void ListVector<T>::write(const value_type &elemento, position p){

	if((p>0) && (p<lunghezza+1))
		elementi[p-1] = elemento;
}


template<class T>
typename ListVector<T>::position ListVector<T>::begin() const{
	return(1);
}


template<class T>
bool ListVector<T>::end(position p) const{

	if ((p > 0) && (p <= lunghezza + 1))
		return( p == lunghezza + 1);
	else
		return(false);
}


template<class T>
typename ListVector<T>::position ListVector<T>::next(position p) const{

	if ((p > 0) && (p < lunghezza + 1))
		return(p+1);
	else
		return(p);
}


template<class T>
typename ListVector<T>::position ListVector<T>::previous(position p) const{

	if ((p > 1) && (p < lunghezza + 1))
		return(p-1);
	else
		return(p);
}


template<class T>
void ListVector<T>::insert(const value_type &a, position p){
  if (lunghezza == dimensioneArray){
    cambiaDimensione(elementi, dimensioneArray, dimensioneArray * 2);
    dimensioneArray = dimensioneArray * 2;
  }
  if ((p > 0) && (p <= lunghezza + 1)) {
		for (int i=lunghezza; i >= p; i--){
			elementi[i] = elementi[i-1];
		}
		elementi[p-1]=a;
		lunghezza++;
	}
}


template<class T>
void ListVector<T>::cambiaDimensione(T*& array, int vecchiaDimensione, int nuovaDimensione){

  T* temp = new T[nuovaDimensione];
  int numero;
  if (vecchiaDimensione < nuovaDimensione)
     numero = vecchiaDimensione;
  else
     numero = nuovaDimensione;
  for (int i=0; i<numero; i++)
     temp[i] = array[i];

  delete [] array;
  array = temp;

}


template<class T>
void ListVector<T>::erase(position p){
  if ( (p > 0) && ( p < lunghezza + 1)) // precondizione
    if (!empty()) {
			for (int i=p-1; i<(lunghezza-1); i++)
				elementi[i] = elementi[i+1];
			lunghezza--;
		}
}


La parte di codice che non ho capito bene è questa:

template<class T>
typename ListVector<T>::value_type ListVector<T>::read(position p) const{

	if((p > 0) && (p < lunghezza + 1))
		return(elementi[p-1]);
}

I miei dubbi sono:
1 - Cosa sta ad indicare quel "typename ListVector<T>::value_type ListVector<T>:: ..." nell'intestazione della funzione? Come dovrei leggerlo?. Ho capito che il "typename" serve ad indicare al compilatore che stiamo lavorando con un determinato tipo ma non capisco cosa stiamo dicendo al compilatore scrivendo così.
2 - La funzione "read" sopra è vincolata da un if, nel caso l'if non si verifica cosa restituisce?

2 Risposte

  • Re: Dubbi sull'uso di typename in C++

    Typename sta a dire al compilatore: value_type è un tipo membro di ListVector<T>, non il nome di una variabile o di una funzione della classe. In poche parole read() restituisce value_type. Va messo essendo quella una classe template e in questo caso il compilatore non è in grado di capirlo da solo.
    Un modo più elegante per rinominare i tipi a partire da C++11 è usare la using:
    using value_type = T;
    Sulla seconda domanda hai ragione. Se non da errore di compilazione, in esecuzione restituisce un valore casuale nel caso l'if risulti falso.
  • Re: Dubbi sull'uso di typename in C++

    Alexv ha scritto:


    Typename sta a dire al compilatore: value_type è un tipo membro di ListVector<T>, non il nome di una variabile o di una funzione della classe. In poche parole read() restituisce value_type. Va messo essendo quella una classe template e in questo caso il compilatore non è in grado di capirlo da solo.
    Un modo più elegante per rinominare i tipi a partire da C++11 è usare la using:
    using value_type = T;
    Sulla seconda domanda hai ragione. Se non da errore di compilazione, in esecuzione restituisce un valore casuale nel caso l'if risulti falso.
    Grazie mi hai chiarito il dubbio! Effettivamente era una stupidata ma davvero non ne stavo venendo fuori da solo . Per la seconda domanda evidentemente è un errore di cui il prof non si è accorto.
Devi accedere o registrarti per scrivere nel forum
2 risposte