Newsgroup: it.comp.lang.c++
Titolo: Funzioni che restituiscono costanti del compilatore ?!?!?

Imbattendomi in un paragrafo sulle template functions di "Thinking in C++
volume 2", ho trovato questa cosa :
// Uses template type induction to
// discover the size of an array
template<typename T, int size>
int asz(T (&)[size]) { return size; }
This actually figures out the size of an array as a compile-time constant
value, without using any sizeof( ) operations! Thus you can have a much more
succinct way to calculate the size of an array at compile time [...]
Incuriosito ho provato a vedere se funziona, ma (come mi aspettavo), anche
con questo codice:
template <typename T,int size>
inline const int sz(T (&) [size]){return size;}
int main(){
 int arr[20];
 const int dim=sz(arr);
 int arr2[dim];
 return 0;
}
il compilatore mi dice :
error: constant value is not known
   int arr2[dim];
... A me sembra che in effetti fa bene il compilatore a lamentarsi, in
quanto penso che nessuna funzione possa in alcun modo restituire un *valore*
che sia una costante del compilatore. Mi sbaglio ? E se non mi sbaglio io,
ha preso un granchio Bruce Eckel ??
Grazie!
--
imho

 ha preso un granchio Bruce Eckel ??
sz restituira' una costante, nel senso che, la funzione stessa avra' il
valore "hard-coded".
Questo non autorizza l'utilizzatore a mettere il risultato in una
variabile e pretendere di poterla usare come costante a tempo di
compilazione.
In altre parole il valore restituito da sz e' una costante, ma in main
il compilatore non lo puo' sapere.
 bye
	av.

 Grazie!
Se ho capito bene quello che dici, Eckel ha ragione ma te lo hai
interpretato male. dim non può essere usata per specificare la
dimensione di un array, perchè è il risultato di una chiamata a
funzione. Comunque, su ogni compilatore in grado di ottimizzare il
codice al posto della chiamata a sz ti vedrai il suo risultato, ovvero
in questo caso 20, in quanto è una funzione che può essere valutata a
compile-time. Ciononostante, non può essere usata per specificare la
dimensione di un array in quanto è pur sempre una funzione: in pratica
la si può calcolare a compile-time, ma semanticamente una funzione
viene calcolata a run-time e quindi non va bene ;-)
Spero di non aver detto troppe scemenze...
-- 
Andrea Bergia - studente              Linux Registered User #281550

 funzione [...]
Rispondo sia a te che a Andrea Venturoli :
A quanto ho capito io, Eckel l'ha usata proprio per specificare a
compile-time la dimensione di un array! Copio cosa c'è scritto :
Thus you can have a much more succinct way to calculate the size of an array
at compile time:
// The return value of the template function
// asz() is a compile-time constant
int main() {
  int a[12], b[20];
  const int sz1 = asz(a);
  const int sz2 = asz(b);
  int c[sz1], d[sz2];
} ///:~
Of course, just making a variable of a built-in type a const does not
guarantee it's actually a compile-time constant, but if it's used to define
the size of an array (as it is in the last line of main( )), then it must be
a compile-time constant.
Effettivamente non si capisce bene se con l'ultima frase intende dire che il
codice sopra scritto non compila oppure compila appunto perché il valore
ritornato da asz lo considera una costante del compilatore... a me
sinceramente sembra che secondo lui quel codice debba compilare!
Grazie comunque.
--
imho

    int arr2[dim];
gia` altri ti hanno detto la ragione dell'errore; se vuoi a tutti i costi
una versione funzionante puo` provare con questo (non testato, ma dovrebbe
funzionare):
template<class T> struct Array_size;
template<class T, int N>
struct Array_size<T[N]>
{
        enum { size = N };
};
int arr[20];
const int sz = Array_size<arr>::size;
int arr2[sz];
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra

 int arr2[sz];
No, non compila...
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg

 No, non compila...
hai perfettamente ragione, ho scritto una bestialita`...


 hai perfettamente ragione, ho scritto una bestialita`...
Almeno ci hai provato. Quindi non si può proprio fare quello che
chiedeva l'OP?


 EMG
--
imho

 sbagliando. Dico bene ?
Prova a riportare l'esempio completo e compilabile cosě lo esamino con
calma.


 chiedeva l'OP?
beh, si puo` fare nel "solito" modo, come si fa anche in C:
const int size = sizeof(MyArray)/sizeof(TypeOfArray);
Il codice che ho scritto io in effetti dovrebbe funzionare, ma con i *tipi*,
non con le *istanze*, ed e` molto utile se si vuole fare un po' di
metaprogrammazione template. Ad esempio:
typedef int ArrayType[20];
const int sz = Array_size<ArrayType>::size;


 const int size = sizeof(MyArray)/sizeof(TypeOfArray);
Allora credo di aver capito male la richiesta iniziale...


 calma.
Incollo l'intero paragrafo, basato sull' esempietto che ho postato
all'inizio :
Type induction in function templates
As a simple but very useful example, consider the following:
//: :arraySize.h
// Uses template type induction to
// discover the size of an array
#ifndef ARRAYSIZE_H
#define ARRAYSIZE_H
template<typename T, int size>
int asz(T (&)[size]) { return size; }
#endif // ARRAYSIZE_H ///:~
This actually figures out the size of an array as a compile-time constant
value, without using any sizeof( ) operations! Thus you can have a much more
succinct way to calculate the size of an array at compile time:
//: C05:ArraySize.cpp
//{-msc}
//{-bor}
// The return value of the template function
// asz() is a compile-time constant
#include "../arraySize.h"
int main() {
  int a[12], b[20];
  const int sz1 = asz(a);
  const int sz2 = asz(b);
  int c[sz1], d[sz2];
} ///:~
Of course, just making a variable of a built-in type a const does not
guarantee it's actually a compile-time constant, but if it's used to define
the size of an array (as it is in the last line of main( )), then it must be
a compile-time constant.
--
imho

 Allora credo di aver capito male la richiesta iniziale...
Non era una richiesta, ho postato quel codice perché mi sembrava strano che
una funzione possa restituire un valore che sia una costante stabilita a
tempo di compilazione ed *usabile* a tempo di compilazione, mentre mi pare
di aver capito che l'autore afferma il contrario (il paragrafo l'ho postato
in un'altra risposta).
--
imho

 in un'altra risposta).
Forse Eckel ha preso un granchio maiuscolo per via del supporto per gli 
array dinamici che c'e` nel GCC (di riflesso per l'adeguamento al C99, 
credo), il quale compila l'esempio fornito senza protestare, a meno di 
specificare l'opzione --pedantic in modo da essere il piu` stringente 
possibile per quanto riguarda codice sorgente non-ISO-compliant).
O forse ho interpretato male quello che voleva dire.
-- 
   |   \    \  | ___|_  |_  | ianezz a casa sua... :-)
   |  _ \  | \ | _|    /   /  Visita il LinuxTrent a
  _|_/  _\_|  _|____|___|___| 
http://www.linuxtrent.it

 chiedeva l'OP?
In realta' si puo' fare come segue (da un post di Rani Sharoni su
comp.lang.c++.moderated):
template <typename T, int SIZE>
char (& lengthof(T (&)[SIZE]) )[SIZE];
#define lengthof(arr) sizeof(lengthof(arr))
il problema e' che per ottenere la deduzione degli argomenti bisogna
usare una funzione template, ma per ottenere una costante di
compilazione non la si puo' chiamare.
Il trucco qui sopra si basa sul fatto che sizeof applicato ad una
funzione restituisce la dimensione del valore ritornato senza chiamare
la funzione stessa. Rani dichiara quindi una funzione template che
prende come argomento un reference ad un generico array e restituisce un
reference ad un array di caratteri della stessa dimensione. Applicando
sizeof al risultato si ottiene il numero di elementi dei due array.
Ciao,
Nicola
P.S. Sono abbastanza colpito dalla frequenza con la quale argomenti
strettamente correlati tendono a comparire quasi contemporaneamente su
newsgroup distinti...
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG


Mi sembra di aver letto un articolo che spiegava come farlo, mi sembra
su C++ Informer di Carlo Pescio, ora pero' non ricordo esattamente...
 bye
	av.

 Grazie comunque.
Di niente.
 bye
	av.

 su C++ Informer di Carlo Pescio, ora pero' non ricordo esattamente...
Lo trovi su 
http://www.eptacom.net


 newsgroup distinti...
Speriamo siano sempre argomenti interessanti come questo.


 [...]
Ok ... comunque non c'è modo di ottenere informazioni sulla grandezza di un
tipo facendo a meno dell'operatore sizeof() a quando pare!
--
imho

 tipo facendo a meno dell'operatore sizeof() a quando pare!
In effetti e' cosi', anche se in questo caso l'uso che se ne fa e'
concettualmente diverso. sizeof applicato al tipo ritornato da una
funzione e' l'unico modo conosciuto per sfruttare a compile time la
deduzione degli argomenti.
Ciao,
Nicola
