Newsgroup: it.comp.lang.c++
Titolo: Esercizio impossibile?

Scrivere un class template che possa essere usato nel modo seguente:
// prints "long const*&"
std::cout << type_descriptor<long const*&>();
// prints "long const*& volatile"
std::cout << type_descriptor<long const*& volatile>();
Sinceramente credo proprio che sia impossibile ottenere l'effetto 
voluto. Da quando lo è?
Kiuhnm

 std::cout << type_descriptor<long const*& volatile>();
Sei sicuro che questo sia un tipo valido? A mio avviso i reference non
possono essere ne volatile ne const.
Ciao,
Nicola

 possono essere ne volatile ne const.
Il codice è valido, ma il VC++ mi dice "warning C4227: anachronism used 
: qualifiers on reference are ignored".
Kiun

 : qualifiers on reference are ignored".
Credo che abbia ragione Nicola. Il gcc (3.4.5) non accetta la sintassi:
long const value = 10;
long const * ptr_val = & value;
long const * & volatile ref_p_v = ptr_val;
error: `volatile' qualifiers cannot be applied to `const long int*&'
Ciao.
-- 
Qual'e' il colmo per uno studente-lavoratore?
Avere un quadrato che si crede un rettangolo.

 Credo che abbia ragione Nicola. Il gcc (3.4.5) non accetta la sintassi:
Sto usando il VC++ con /Za e /W4.
Non segue lo standard neanche così???
Kiuhnm

 Non segue lo standard neanche così???
Forse era una pratica pre-standard "definitivo".
Kiuhnm

Non so se è come te lo immaginavi, ma credo che questo sia quello che
al massimo si può fare.
Ciao
Gianluca
PS l'ho testato con CW9.4. Non so funziona anche con VC++7.1
#include <iostream>
#include <ostream>
#include <string>
template<class T>
struct type_descriptor;
template<>
struct type_descriptor<char>
{
	static std::string name()
	{
		return "char";
	}
};
template<>
struct type_descriptor<short>
{
	static std::string name()
	{
		return "short";
	}
};
template<>
struct type_descriptor<int>
{
	static std::string name()
	{
		return "int";
	}
};
template<>
struct type_descriptor<long>
{
	static std::string name()
	{
		return "long";
	}
};
template<>
struct type_descriptor<unsigned char>
{
	static std::string name()
	{
		return "unsigned char";
	}
};
template<>
struct type_descriptor<unsigned short>
{
	static std::string name()
	{
		return "unsigned short";
	}
};
template<>
struct type_descriptor<unsigned int>
{
	static std::string name()
	{
		return "unsigned int";
	}
};
template<>
struct type_descriptor<unsigned long>
{
	static std::string name()
	{
		return "unsigned long";
	}
};
template<class T>
struct type_descriptor<T const>
{
	static std::string name()
	{
		return type_descriptor<T>::name() + " const";
	}
};
template<class T>
struct type_descriptor<T volatile>
{
	static std::string name()
	{
		return type_descriptor<T>::name() + " volatile";
	}
};
template<class T>
struct type_descriptor<T*>
{
	static std::string name()
	{
		return type_descriptor<T>::name() + " *";
	}
};
template<class T>
struct type_descriptor<T&>
{
	static std::string name()
	{
		return type_descriptor<T>::name() + "&";
	}
};
template<class T>
std::ostream& operator<<(std::ostream& os, type_descriptor<T> const&
desc)
{
	return os << 
desc.name
();
}
int main()
{
	std::cout << type_descriptor<long const*&>() << std::endl;
}

 
Nel tuo codice c'è un piccolo errore che affliggeva anche il mio, 
inzialmente. I template sono veramente infidi.
Prova
std::cout << type_descriptor<long const volatile>() << std::endl;
I nostri codici sono molto simili, anche se io non ho avuto l'accortezza 
di raccogliere operator<<, ma l'ho riscritto per ogni struttura (il 
numero di righe è uguale, comunque :) ).
Kiuhnm

Hai ragione!
Ma basta aggiungere
template<class T>
struct type_descriptor<T const volatile>
{
/*
etc...
*/
};
Ciao
Gianluca

 Forse era una pratica pre-standard "definitivo".
Secondo me quando VC++ ti dice "qualifiers on reference are ignored"
semplicemente ti avverte che sta ignorando il "volatile" che c'e' in fondo
al tuo tipo, quindi "long const * & volatile" diventa uguale a "long const
* &", impedendoti di fatto di discriminare tra i due con la
metaprogrammazione...
Il gcc e' un po' piu' rigoroso e non ti lascia proprio scrivere quel codice.


 metaprogrammazione...
Sì, è così. Non a caso nel post iniziale ho scritto due casi che 
differiscono solo per il qualificatore "volatile".
Però il termine "anacronistico" fa pensare che in passato si potesse 
fare. Nei vecchi codici si trova.
Kiuhnm

 };
Sì, è una fortuna che in C++ i qualificatori (const e volatile) siano 
soltanto due.
Kiuhnm