Marco De Paoli wrote: > ciao a tutti, > vorrei fare un ciclo statico su una tupla di n interi
Non conosco benissimo boost::tuple, ma con poche righe di codice (che metto in fondo al messaggio) ho creato una funzione template 'for_each', che ti permette di invocare un oggetto funzione su ogni elemento della tupla.
struct print { template< class T > void operator()( const T& v ) { cout << v << endl; } };
Ovviamente si possono fare cose pi sofisticate, e pi eleganti, come quelle che fa fusion. Ma se ti basta questo, il codice sotto la firma.
Max
#include "boost/tuple/tuple.hpp"
template< int Num, class Tuple, class Pred > struct for_each_impl { for_each_impl( const Tuple& t, Pred op ) { using namespace boost; // non ho capito perch , ma senza questo using non compila for_each_impl<Num-1,Tuple,Pred> prev(t,op); op( t.get<Num>() ); }
};
template< class Tuple, class Pred > struct for_each_impl<0,Tuple,Pred> { for_each_impl( const Tuple& t, Pred op ) { using namespace boost; op( t.get<0>() ); }
};
template< class Tuple, class Pred > void for_each( const Tuple& t, Pred op ) { for_each_impl< tuples::length<Tuple>::value-1,Tuple,Pred> impl(t,op);
On 18 Lug, 20:40, "Max M." <ed...@maxim.comm2000.it> wrote:
> Non conosco benissimo boost::tuple, ma con poche righe di codice (che metto > in fondo al messaggio) ho creato una funzione template 'for_each', che ti > permette di invocare un oggetto funzione su ogni elemento della tupla.
pensavo a qualcosa di già pronto (magari in qualche parte di boost che non conoscevo) Max, me lo hai addirittura implementato :-)
grazie, Marco
P.S. per la cronaca sul VC2500 non serve using namespace boost;
> P.S. per la cronaca sul VC2500 non serve > using namespace boost;
Visto che anche uno dei GCC più recenti (4.1.3) non compila quel codice senza aggiungere lo 'using', mi piacerebbe capire quale dovrebbe essere il comportamento del compilatore a norma di standard.
> > P.S. per la cronaca sul VC2500 non serve > > using namespace boost;
> Visto che anche uno dei GCC più recenti (4.1.3) non compila quel codice > senza aggiungere lo 'using', mi piacerebbe capire quale dovrebbe essere il > comportamento del compilatore a norma di standard.
> Mi pare che in questi casi la keyword "template" sia in effetti > obbligatoria, essendo 'get' un "dependent name".
> Il fatto che GCC lo compili con lo 'using' semprerebbe, perciò, accidentale.
> Max
ho dato un occhiata agli header di tuple: get è un metodo di un ancestor di tuple di conseguenza non dovrebbe neanche servire scomodare il Koenig lookup per rintracciarlo: è semplicmente un metodo ereditato dalla classe
sinceramente non capisco perchè sia necessaria la keyword "template" (o in alternativa lo "using")
Marco De Paoli wrote: > ho dato un occhiata agli header di tuple: get è un metodo di un > ancestor di tuple di conseguenza non dovrebbe neanche servire > scomodare il Koenig lookup per rintracciarlo: è semplicmente un > metodo ereditato dalla classe
Sì, però, poiché la mia classe è templatizzata proprio sul tipo a cui viene applicato 'get', quel nome è un "dependent name". Questo dettaglio è essenziale.
> sinceramente non capisco perchè sia necessaria la keyword > "template" (o in alternativa lo "using")
La keyword 'template' è necessaria perché lo Standard richiede che il compilatore abbia informazioni sufficienti per disanbiguare sintatticamente l'espressione in questione prima dell'effettiva instanziazione. Sapere che un "dependent name" si riferisce a un template, consente di decidere come interpretare il segni '<' e '>', che altrimenti genererebbero ambiguità. Basta considerare questo codice
t.get<0>(arg) ;
e immaginare di instanziarlo per un tipo che abbia un membro 'get', a cui sia possibile applicare l'operatore '<'.
Gli estensori dello Standard hanno deciso che certe ambiguità devono essere risolte nella primissima fase di compilazione di un template.
Alcuni compilatori, evidentemente, posticipano tutte le decisioni al momento in cui il template viene istanziato. Questo non è conforme allo Standard, e può portare a istanziazioni che non dovrebbero essere consentite.
Non so perché, invece, GCC compili quel codice se si aggiunge lo 'using'. Non trovo ragioni valide, e -come ho detto- tendo a credere che sia un fatto accidentale.
On 21 Lug, 16:56, "Max M." <ed...@maxim.comm2000.it> wrote:
> Sì, però, poiché la mia classe è templatizzata proprio sul tipo a cui viene > applicato 'get', quel nome è un "dependent name". Questo dettaglio è > essenziale. > La keyword 'template' è necessaria perché lo Standard richiede che il > compilatore abbia informazioni sufficienti per disanbiguare sintatticamente > l'espressione in questione prima dell'effettiva instanziazione. Sapere che > un "dependent name" si riferisce a un template, consente di decidere come > interpretare il segni '<' e '>', che altrimenti genererebbero ambiguità. > Basta considerare questo codice
> t.get<0>(arg) ;
> e immaginare di instanziarlo per un tipo che abbia un membro 'get', a cui > sia possibile applicare l'operatore '<'.
si, adesso è chiaro
> Gli estensori dello Standard hanno deciso che certe ambiguità devono essere > risolte nella primissima fase di compilazione di un template.
> Alcuni compilatori, evidentemente, posticipano tutte le decisioni al momento > in cui il template viene istanziato. Questo non è conforme allo Standard, e > può portare a istanziazioni che non dovrebbero essere consentite.
> Non so perché, invece, GCC compili quel codice se si aggiunge lo 'using'. > Non trovo ragioni valide, e -come ho detto- tendo a credere che sia un > fatto accidentale.
quello che mi lascia perplesso è che boost::tuple faccia conto su questo comportamento non standard dei compilatori...
> quello che mi lascia perplesso è che boost::tuple faccia conto su > questo comportamento non standard dei compilatori...
Scusami, non capisco il tuo commento. La sintassi senza la keyword "template" è prefettamente legale, a condizione che l'oggetto sia di un tipo ben preciso, nel senso che non sia (o non dipenda da) un parametro di un template. Vale in sostanza lo stesso principio della keyword "typename": se non si tratta di un "dependent name", non bisogna usarla.
On 22 Lug, 12:16, "Max M." <ed...@maxim.comm2000.it> wrote:
> > quello che mi lascia perplesso è che boost::tuple faccia conto su > > questo comportamento non standard dei compilatori...
> Scusami, non capisco il tuo commento. La sintassi senza la keyword > "template" è prefettamente legale, a condizione che l'oggetto sia di un > tipo ben preciso, nel senso che non sia (o non dipenda da) un parametro di > un template. Vale in sostanza lo stesso principio della keyword "typename": > se non si tratta di un "dependent name", non bisogna usarla.
certo hai ragione non avevo colto appieno il "dettaglio essenziale"
> Sì, però, poiché la mia classe è templatizzata proprio sul tipo a cui viene > applicato 'get', quel nome è un "dependent name".
messa così la cosa effettivamente non capisco cosa cambi al compilatore sapere che siamo nel namespace boost
sono io programmatore nella definizione del template for_each_impl che devo "chiedere esplicitamente" che il tipo Tuple abbia un template method di nome "get"
giusto? ho capito bene il punto oppure continua a sfuggirmi qualcosa?
se ho capito bene non sono comunque in grado di rispondere al tuo dubbio
perchè dovrebbe essere necessario "using namespace boost"?
in effetti boost::tuple è il tipo effettivo su cui viene istanziato il template il fatto che per il gcc l'uso della direttiva "using namespace boost" faccia differenza sembra confermare la tua ipotesi: il compilatore attende una fase successiva, nella quale ha maggiori informazioni, per mappare l'identificatore "get" sul metodo "tuple::get" a quel punto è ovviamente anche in grado di dedurre che "get" è un template method e non un membro o un tipo
Marco De Paoli wrote: > sono io programmatore nella definizione del template for_each_impl che > devo "chiedere esplicitamente" che il tipo Tuple abbia un template > method di nome "get"
> giusto? > ho capito bene il punto oppure continua a sfuggirmi qualcosa?
Giusto. (Sempre che io non stia prendendo una cantonata; ogni tanto mi càpita.)
> perchè dovrebbe essere necessario "using namespace boost"?
Infatti, secondo me è un effetto accidentale di qualche dettaglio implementativo del GCC.
Con o senza 'using', il codice non è legale se non si aggiunge 'template'. Perciò entrambi i compilatori -VC2005 e GCC4- non rispettano lo standard in questo aspetto. (Credo.)