06/11/15 10:52
AldoBaldo
Ciao a tutti.
Stavo cercando di aggiungere le funzioni template all'insieme delle mie (limitate) conoscenze, ma mi trovo di fronte a una cosa che non riesco a capire da solo. Ho già provato ad aggiungere un paio di bicchieri di buon rosso per rafforzare la capacità d'introspezione ma niente da fare -- il mistero non si dipana. Prima di cadere nella spirale senza fine dell'alcolismo provo a chiedere il vostro prezioso aiuto. La questione è questa...
Perché diavolo la funzione template CompattaArray() in questo codice funziona per i valori double e int e non per le stringhe const char * ?
Il compilatore mastica tutto, quindi sputa fuori questa odiosa raffica di sentenze, secondo me con la chiara intenzione di denigrare i miei sforzi con una palese dose di sadismo:
||=== Build: Release in Prova fTemplate (compiler: GNU GCC Compiler) ===|
\main.cpp||In function 'int main()':|
\main.cpp|23|error: no matching function for call to 'CompattaArray(const char* [6], const unsigned int&, bool (&(const char*), const char**)'|
\main.cpp|23|note: candidate is:|
\main.cpp|5|note: template<class tipo> unsigned int CompattaArray(tipo*, unsigned int, bool (*)(tipo*), const tipo*)|
\main.cpp|5|note: template argument deduction/substitution failed:|
\main.cpp|23|note: deduced conflicting types for parameter 'tipo' ('const char*' and 'const char')|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
(Ho eliminato tutti i riferimenti al percorso del file main.cpp, per sintetizzare, tanto sono irrilevanti in questo contesto.)
Credo che la chiave possa essere in quel conflicting types for parameter 'tipo', ma non capisco da cosa possa nascere il conflitto. Il compilatore non dovrebbe sostituire "tipo" con "const char*" e accettare aPtr (l'array di stringhe const char* in main) come un puntatore ad un array di const char*, ovvero come tipo* ? Non dovrebbe valere la stessa cosa anche per nPtr? No, pare proprio di no, ma non capisco perché. Sto già versando il terzo bicchiere di rosso.
Stavo cercando di aggiungere le funzioni template all'insieme delle mie (limitate) conoscenze, ma mi trovo di fronte a una cosa che non riesco a capire da solo. Ho già provato ad aggiungere un paio di bicchieri di buon rosso per rafforzare la capacità d'introspezione ma niente da fare -- il mistero non si dipana. Prima di cadere nella spirale senza fine dell'alcolismo provo a chiedere il vostro prezioso aiuto. La questione è questa...
Perché diavolo la funzione template CompattaArray() in questo codice funziona per i valori double e int e non per le stringhe const char * ?
#include <stdio.h> #include <string.h> template <class tipo> // prototipo della funzione template unsigned int CompattaArray( tipo *a, unsigned int totEl, bool fNullita(tipo*), const tipo *nullo = NULL ); // prototipi delle funzioni di verifica // delle condizioni di nullita' (esempi) bool CondizioneNullitaPtr( const char *e ); bool CondizioneNullitaDouble( double *e ); bool CondizioneNullitaInt( int *e ); int main() { const unsigned int totEl = 6; unsigned int nElValidi = 0; // tutti i puntatori NULL vengono "cassati" // gli elementi "residui" vengono annullati const char *aPtr[totEl] = {"a","b",NULL,"c","d","e"}; const char *nPtr = NULL; nElValidi = CompattaArray( aPtr, totEl, CondizioneNullitaPtr, &nPtr ); for( unsigned int i=0; i<totEl; ++i ) printf( "0x%08X\n", (unsigned int)aPtr[i] ); printf( "%u elementi validi\n\n", nElValidi ); // tutti i valori inferiori a 0.5 vengono "cassati"; // gli elementi "residui" NON vengono annullati double aDouble1[totEl] = {1.0,0.5,0.0,0.49,2.76,0.54}; nElValidi = CompattaArray( aDouble1, totEl, CondizioneNullitaDouble ); for( unsigned int i=0; i<totEl; ++i ) printf( "%f ", aDouble1[i] ); printf( "\n%u elementi validi\n\n", nElValidi ); // tutti i valori inferiori a 0.5 vengono "cassati"; // gli elementi "residui" vengono annullati double aDouble2[totEl] = {1.0,0.5,0.0,0.49,2.76,0.54}; double nDouble = 0.0; // valore di annullamento double nElValidi = CompattaArray( aDouble2, totEl, CondizioneNullitaDouble, &nDouble ); for( unsigned int i=0; i<totEl; ++i ) printf( "%f ", aDouble2[i] ); printf( "\n%u elementi validi\n\n", nElValidi ); // tutti i valori non compresi tra 5 e 10 vengono "cassati"; // gli elementi "residui" vengono annullati int aInt[totEl] = {1,6,8,-2,10,11}; int nInt = 0; // valore di annullamento int nElValidi = CompattaArray( aInt, totEl, CondizioneNullitaInt, &nInt ); for( unsigned int i=0; i<totEl; ++i ) printf( "%d ", aInt[i] ); printf( "\n%u elementi validi\n\n", nElValidi ); return 0; } template <class tipo> unsigned int CompattaArray( tipo *a, unsigned int totEl, bool fNullita(tipo*), const tipo *nullo ) { unsigned int i, j; for( i=j=0; i<totEl; ++i ) if( !fNullita(&(a[i])) ) a[j++] = a[i]; if( nullo ) for( i=j; i<totEl; ++i ) a[i] = *nullo; return j; // la quantita' degli elementi non nulli // "raggruppati" in testa all'array } bool CondizioneNullitaPtr( const char *e ) { // CompattaArray() elimina tutti i puntatori NULL return e == NULL; } bool CondizioneNullitaDouble( double *e ) { // CompattaArray() elimina tutti i valori inferiori a 0.5 return *e < 0.5; } bool CondizioneNullitaInt( int *e ) { // CompattaArray() elimina tutti i valori non compresi tra 5 e 10 return *e < 5 || *e > 10; }
Il compilatore mastica tutto, quindi sputa fuori questa odiosa raffica di sentenze, secondo me con la chiara intenzione di denigrare i miei sforzi con una palese dose di sadismo:
||=== Build: Release in Prova fTemplate (compiler: GNU GCC Compiler) ===|
\main.cpp||In function 'int main()':|
\main.cpp|23|error: no matching function for call to 'CompattaArray(const char* [6], const unsigned int&, bool (&(const char*), const char**)'|
\main.cpp|23|note: candidate is:|
\main.cpp|5|note: template<class tipo> unsigned int CompattaArray(tipo*, unsigned int, bool (*)(tipo*), const tipo*)|
\main.cpp|5|note: template argument deduction/substitution failed:|
\main.cpp|23|note: deduced conflicting types for parameter 'tipo' ('const char*' and 'const char')|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
(Ho eliminato tutti i riferimenti al percorso del file main.cpp, per sintetizzare, tanto sono irrilevanti in questo contesto.)
Credo che la chiave possa essere in quel conflicting types for parameter 'tipo', ma non capisco da cosa possa nascere il conflitto. Il compilatore non dovrebbe sostituire "tipo" con "const char*" e accettare aPtr (l'array di stringhe const char* in main) come un puntatore ad un array di const char*, ovvero come tipo* ? Non dovrebbe valere la stessa cosa anche per nPtr? No, pare proprio di no, ma non capisco perché. Sto già versando il terzo bicchiere di rosso.
ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.