Newsgroup: it.comp.lang.c++
Titolo: metaprogrammazione template e strutture

Salve a tutti, ho provato a cercare un pò in giro ma non ho trovato
nessun esempio che mi potesse aiutare. Ho letto che è possibile
utilizzare i template per realizzare delle "tabelle" e in particolare
venivano citate tabelle di seni e coseni calcolati (per l'appunto
grazie ai template) a tempo di compilazione. Vorrei una realizzare una
cosa simile, per definire attraverso un template ricorsivo un array o
vettore di interi, con il primo elemento pari a 100 e l'elemento n+1
pari a n + n - (n-1) * 1.5. Sarei grato a chi potesse fornirmi un aiuto
o un esempio abbastanza calzante.
Grazie


Cerca Boost, MPL e preprocessor library.
Per me non ne vale la pena. Si fa molto prima a crearsi un tool esterno 
per questo genere di cose. Fai un make file che prima genera il tool e 
poi lo usa per generare il file cpp e quindi genera l'intero progetto.
Kiuhnm

 ha scritto nel messaggio 
news:1155670258....@b28g2000cwb.googlegroups.com...

Una cosa del genere?
#include <iostream>
struct Formula
{
    static int formula( int i, int n ) { return i == 0 ? 100 : n + n - ( n - 
1 ) * 1.5; }
};
template < int i, int j > struct T;
template < int i > struct T < i, 0 >
{
    T() {}
    int val[ i ];
    int operator [] ( int n ) const { return val[ n ]; }
};
template < int i, int j > struct T: public T < i, j - 1 >
{
    T() { val[ j - 1 ] = Formula::formula( j - 1, val[ j - 2 ] ); }
};
template < int Items > struct Tabella: public T < Items, Items >
{
    Tabella():size( Items ) {}
    int size;
};
int main()
{
    const Tabella < 5 > t;
    for ( int i = 0; i < t.size; ++i )
        std::cout << t[ i ] << std::endl;
    return 0;
}
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
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 

 EMG
Ti ringrazio, è esattamente quello di cui avevo bisogno.

 }
Cosě a occhio, direi che questo codice presenta almeno due problemi: t 
viene creato a RUN-time e Items non puň essere troppo elevato (< 200?).
Ma dopo ci guardo con piů calma e soprattutto provo a compilarlo.
Kiuhnm

 Ma dopo ci guardo con piů calma e soprattutto provo a compilarlo.
Grazie.


 Grazie.
Sě, non funziona. Hai per giunta un overhead piuttosto elevato perché il 
compilatore non scrive in linea funzioni che chiamano sé stesse piů di n 
volte.
Considera il codice seguente:
----
#include <iostream>
template <int n>
struct Table
{
	int t[n];
	Table()
	{
		for (int i = 0; i < n; i++)
			t[i] = i;
	}
	int& operator[](int i) { return t[i]; }
	static const int size = n;
};
Table<7> t;
int main()
{
	for ( int i = 0; i < t.size; ++i )
		std::cout << t[ i ] << std::endl;
	return 0;
}
----
Il VC8 (2005) genera la tavola 't' in compile time e la inserisce 
direttamente nel file exe. In questo modo viene copiata in memoria 
direttamente dall'OS.
Il problema č che se al posto di 7 si usa 10, il compilatore decide di 
generare la tavola in run-time.
Allora dovrebbe essere teoricamente possibile dire al compilatore di 
inserire la tavola direttamente nell'.exe qualunque sia la sua 
dimensione. Nel caso dell'esempio non c'č alcun guadagno, ma se si 
dovessero calcolare funzioni complesse la storia sarebbe diversa.
I template vanno bene per calcolare, ma non per "immagazzinare".
Per quest'ultima cosa č meglio usare preprocessore.
Kiuhnm

 Considera il codice seguente:
Che comunque mi sembra ben diverso dal mio, o sbaglio? Considera che non sono 
affatto un esperto di templates.


 affatto un esperto di templates.
Considera la struttura "Formula". Non puoi usare una funzione! Devi 
usare una metafunzione che restituisce il valore o tramite uno static 
const o, meglio, tramite un tipo numerico come Num<0> (typedef).
Quando scrivi "int val[i];" ti sei già precluso la strada al 
compile-time, perché devi usare un costruttore per inizializzare l'array 
e i costruttori vengono chiamati a run-time.
E' necessario scrivere "int val[i] = {val1, val2, ...};", ma ciò non è 
ovviamente possibile.
Quindi l'unica è servirsi del preprocessore. In realtà sarei curioso di 
sapere come dire al VC8 di inserire la struttura precalcolata nell'.exe 
ignorandone la dimensione. Deve esserci un modo...
Kiuhnm

 tratterebbe comunque di una ottimizzazione.
Ok, tengo per buono il tuo giudizio fino a prova contraria, grazie.


 Ok, tengo per buono il tuo giudizio fino a prova contraria, grazie.
Non tutto è come sembra. Considera questo piccolo codice:
---
#include <iostream>
struct L0 { int a,b; };
struct L1 { L0 a,b; };
struct L2 { L1 a,b; };
struct L3 { L2 a,b; };
struct L4 { L3 a,b; };
struct L5 { L4 a,b; };
struct L6 { L5 a,b; };
struct L7 { L6 a,b; };
struct L8 { L7 a,b; };
struct L9 { L8 a,b; };
struct LA { L9 a,b; };
struct LB { LA a,b; };
struct LC { LB a,b; };
struct LD { LC a,b; };
struct LE { LD a,b; };
struct LF { LE a,b; };
struct L10 { LF a,b; };
struct L11 { L10 a,b; };
struct L12 { L11 a,b; };
struct L13 { L12 a,b; };
struct L14 { L13 a,b; };
struct L15 { L14 a,b; };
const L0 l0 = {1,1};
const L1 l1 = {l0,l0};
const L2 l2 = {l1,l1};
const L3 l3 = {l2,l2};
const L4 l4 = {l3,l3};
const L5 l5 = {l4,l4};
const L6 l6 = {l5,l5};
const L7 l7 = {l6,l6};
const L8 l8 = {l7,l7};
const L9 l9 = {l8,l8};
const LA lA = {l9,l9};
const LB lB = {lA,lA};
const LC lC = {lB,lB};
const LD lD = {lC,lC};
const LE lE = {lD,lD};
const LF lF = {lE,lE};
const L10 l10 = {lF,lF};
const L11 l11 = {l10,l10};
const L12 l12 = {l11,l11};
const L13 l13 = {l12,l12};
const L14 l14 = {l13,l13};
const L15 l15 = {l14,l14};
int main()
{
	std::cout << l15.a.b.a.b.a.b.a.b.b.b.b.a.b.b.b.a.b.a.b.a.a.b << std::endl;
	std::cout << sizeof(l15) << std::endl;
	return 0;
}
---
Guarda quanto è grande l15 e quanto è grande il file .exe. Com'è 
possibile? Per es. il VC8 usa molte memcpy in run-time per inizializzare 
l15. Si può avere la certezza quasi assoluta che tutto il codice venga 
generato off-line, ma per quanto riguarda i dati non c'è certezza.
Kiuhnm