Newsgroup: it.comp.lang.c++
Titolo: Stringa come parametro classe template

Salve,
c'è un modo di utilizzare una costante stringa come parametro di una classe 
template ?
Io ho provato con:
template<const char* const stringa>
class prova {/*...*/};
ma quando dichiaro un istanza della classe:
prova<"Ciao !!"> mia_prova;
il compilatore (gcc) protesta (string literal "Ciao !!" is not a valid 
template argument because it is the address of an object with static 
linkage).
C'è un modo di far funzionare la cosa ?
Grazie !! :)
-- 
Lorenzo


Sarebbe piů razionale una cosa del tipo:
template <typename Stringa>
class prova{
public:
    Stringa testo;
    prova(Stringa str){
        testo=str;
    }
//
};
e poi un'istanza:
prova<char *> mia_prova="Ciao";
anche se cosě non viene copiata visto che si tratta di un puntatore (cmq non
l'ho compilato) ... Mi viene il dubbio che tu non abbia troppo chiaro come
si usano i template e a cosa servono...
Bye
Antonio

 prova<"Ciao !!"> mia_prova;
I letterali hanno linkage statico e non possono essere usati come argomenti 
di un template. Se vuoi instanziare il tuo template devi usare l'indirizzo 
di un array con linkage globale.
In un header dichiari questo:
 extern char ciao_ciao[ 10 ];
In una sola unità di compilazione lo definisci:
 char ciao_ciao[ 10 ] = "ciao ciao";
E poi instanzi così:
 prova<ciao_ciao> mia_prova;
Max

 e a cosa servono...
Senza offesa, ma mi sembra che sei tu che non hai ben chiaro il meccanismo 
dei template in C++. Dovresti sapere che i parametri dei template non sono 
limitati a tipi (class e typename) ma possono comprendere anche oggetti 
costanti noti a tempo di compilazione.
-- 
Lorenzo

 l'indirizzo di un array con linkage globale.
Ho capito... purtroppo però non è una soluzione praticabile nel mio 
progetto. Ci potrebbero essere alternative ? Usando std::string incappo 
nello stesso problema ?
Grazie...:)
-- 
Lorenzo

 costanti noti a tempo di compilazione.
I parametri che non sono tipi sono soggetti a restrizioni molto rigide.
Cito lo Standard:
  [14.3]
  A non-type template-parameter shall have one of the following (option-
  ally cv-qualified) types:
  --integral type, accepting an integral constant expression as an argu-
    ment,
  --enumeration  type,  accepting  an integral constant expression as an
    argument,
  --pointer to object, accepting an address constant  expression  desig-
    nating a named object with external linkage,
  --reference  to  object,  accepting an lvalue expression designating a
    named object with external linkage,
  --pointer to function, accepting an  expression  of  type  pointer  to
    function designating a function with external linkage,
  --reference  to function, accepting an lvalue expression designating a
    function with external linkage,
  --pointer to member, accepting an address constant  expression  desig-
    nating a named member of a class.
Il terzo punto spiega perché non č possibile usare un letterale stringa per 
instanziare un template. Quanto a usare 'std::string' (per rispondere alla 
domanda dell'altro tuo post), dipende tutto dall'uso che ne vuoi fare. Puoi 
usare, ad esempio, un reference a un oggetto 'std::string' con "external 
linkage", ma non so se questo ti puň servire. Forse, se illustri qual č 
precisamente la tua esigenza, si puň vedere di identificare il costrutto 
piů idoneo.
Max

 identificare il costrutto piů idoneo.
Mi serve un meccanismo di asserzioni valutate a tempo di compilazione.
Attualmente uso:
template<bool assertion>
class static_assert {};
template<>
class static_assert<false> {
public:
  static_assert() {throw "static assertion failed";}
};
// ESEMPIO DI UTILIZZO
static_assert<sizeof(int)==4>();
Questo codice fa esattamente ciň che voglio io, valuta l'asserzione a tempo 
di compilazione, se č TRUE non aggiunge nessun overhead (ho controllato 
anche l'assembler generato), mentre se č FALSE lancia un eccezione.
Era utile poter rendere variabile il messaggio di errore, qualcosa di questo 
tipo:
static_assert<sizeof(int)==4,"ERRORE: tipo int non a 32 bit">();
Capito il concetto ? Naturalmente lascia perdere questo esempio particolare, 
che potrebbe essere risolto in tanti altri modi...
-- 
Lorenzo

 che potrebbe essere risolto in tanti altri modi...
Capito il concetto, ma ancora non comprendo quale sarebbe il vantaggio
rispetto, ad esempio, ad aggiungere un secondo argomento al costruttore del
tuo 'static_assert'. Non avresti comunque overhead nel caso 'true'. Io, per
un'esigenza analoga, usavo una cosa del genere:
 template< bool V >  struct is_true        {  enum { value = 1 }; };
 template<>          struct is_true<false> {  enum { value = 0 }; };
 #define STATIC_CHECK_THROW(Expr,Exception,Arg)   if( is_true<Expr>::value )
throw Exception(Arg);
Anche qui, l'overhaead nel caso di 'true' dovrebbe essere nullo.
Max