Newsgroup: it.comp.lang.c++
Titolo: C++0X

Ho dato un'occhata alle innovazioni del C++0x e ho l'impressione che la
sintassi stia diventando sempre meno chiara. Ho visto dei meccanismi che in
qualche modo tentano di simulare alcuni aspetti tipici dei linguaggi
tipizzati dinamicamente, solo che il risultato è un codice sicuramente più
complesso e meno chiaro. Ad esempio questo sarebbe il modo di gestire le
tuple:
Esempio di definizione ed uso di una tupla:
typedef tuple< int, double, long &, const char * > tupla_di_prova ;
long lungo = 12 ;
tupla_di_prova prova( 18, 6.5, lungo, "Ciao!" ) ;
lungo = get<0>(prova) ;  // Assegna a 'lungo' il valore 18.
get<3>(prova) = "Bello!" ;  // Modifica il quarto elemento della tupla.
Mi chiedo quando ci sarà un compilatore 100% compliant con questo nuovo
standard...

Noixe ha scritto:

Non sapevo nulla delle tuple fino ad ora.
Da quello che ho capito è come se si fosse implementata una struct 
semplificata con i metodi di get() e set() indicizzati ai campi?
Maurus

 semplificata con i metodi di get() e set() indicizzati ai campi?
Nell'esempio usa get anche per settare i campi, ma forse � un errore di 
stampa. Su wikipedia ci sono varie spiegazioni sulle novit�, sono proprio 
tante:
http://it.wikipedia.org/wiki/C%2B%2B0x
Comunque, secondo me la potenza e la bellezza di strutture come le tuple da 
il meglio in linguaggi tipizzati dinamicamente. Nel C++ credo contribuir� 
alla nascita di sorgenti molto complessi. 

 stampa.
Probabilmente ci sono due funzioni get, quella const per leggere il 
valore e quella non-const per modificarlo.
E.

 standard...
Non (pre)vedo difficolta' a scrivere un compilatore che gestisca le tuple.
Ma in effetti il nuovo linguaggio sara' piu' complesso di quello attuale 
sia da leggere che da compilare. D'altra parte, per mantenere la 
compatibilita' con le versioni precedenti, non si puo' buttare niente, 
ma si puo' solo aggiungere, e si deve aggiungere in modo da non creare 
ambiguita' con la sintassi esistente.
Tuttavia, credo che le parti piu' ostiche del nuovo C++ verranno usate 
quasi esclusivamente nel codice di libreria (non solo nella libreria 
standard, ma comunque in librerie). Ritengo che invece il codice 
applicativo diventera' piu' semplice da scrivere, piu' semplice da 
leggere, e i messaggi d'errore dei compilatori saranno piu' 
comprensibili, in quanto, utilizzando una libreria ben scritta, il 
compilatore avra' piu' strumenti per diagnosticare correttamente gli 
errori del programmatore applicativo.
-- 
Carlo Milanesi
http://digilander.libero.it/carlmila

 
tuple non ha bisogno del nuovo standard per funzionare, sono state
implementate sullo standard corrente; le puoi trovare qui:
http://www.boost.org/doc/libs/1_39_0/libs/tuple/doc/tuple_users_guide.html

 Non (pre)vedo difficolta' a scrivere un compilatore che gestisca le tuple.
Mi riferisco in generale alle nuove caratteristiche del linguaggio.
Saluti 

 implementate sullo standard corrente;
Vero. Per� l'implementazione di tuple possibile nello standard attuale ha
necessariamente un limite massimo prefissato al numero di elementi, che in
quella di Boost � 10. Nel nuovo standard, invece, 'tuple' si avvale
dei "variadic templates":
   template< class ... Types > class tuple {  ...
Max
 

 sintassi stia diventando sempre meno chiara.
Tra le innovazioni sintattiche di maggior rilievo, c'� sicuramente
l'introduzione delle espressioni lambda e delle closure.
Ora, ad esempio, si potranno scrivere cose del genere:
   int value = 42;
   auto res = std::find_if( 
            beg, 
            end, 
            [=](int x) { return x == value; } 
       );
Si noti anche l'uso della keyword 'auto'.
Max

 Tra le innovazioni sintattiche di maggior rilievo, c'è sicuramente



Potresti commentare un poco lo scopo e la sintassi
dell'esempio che fornisci ? Io non sono neppure riuscito a
intuirne vagamente lo scopo ...
grazie in anticipo
Soviet
Mi pare che cerchi il valore uguale a value in un container di cui beg e end 
sono rispettivamente iteratori al primo ed ultimo elemento (+ 1 se non 
ricordo male)
L'uso di auto dovrebbe indicare l'inizializzazione automatica di res, a 
prescindere dall'esito di find_if? 

 prescindere dall'esito di find_if? 
A occhio direi che "auto" significa che il tipo della variabile lo deve 
capire il compilatore, senza che io glielo debba dire.
E.

 ha scritto:

Fino ad ora la keyword, sebbene il suo utilizzo fosse deprecato, indicava 
che la variabile era automatica, quindi creata e distrutta ogni volta che si 
entrava e si usciva dal blocco operativo della funzione in cui era 
dichiarata, ma ho appena letto che nel nuovo standard:
"Utilizzando la parola chiave auto informiamo il compilatore che il tipo 
della variabile sar� uguale a quello del secondo membro dell'espressione."
Ad esempio:
auto x = 5; // int x = 5;
Quindi la tua ipotesi � corretta.
Inoltre ho notato che � stata introdotta una funzionalit� a cui pensavo vari 
anni fa e che qui si usa tramile la keywrod decltype. In tal modo si pu� 
dichiarare una variabile del tipo di un'altra gi� dichiarata, avendo cosi 
una sorta di dichiarazioni di tipo dipendenti una dall'altra.
Ad esempio:
int x;
decltype(x) y ;  // int y;
Saluti 

Noixe ha scritto:

Ho letto la proposta in italiano su  
http://it.wikipedia.org/wiki/C%2B%2B0x
Deve dire che le proposte sono interessanti ed al contrario di te non 
trovo la definzione e l' uso delle tuple complicata.
E' vero che la definizione di tupla e' in voga in linguaggi dinamici 
come python e perl ma in questo caso il tutto e' risolto , grazie ai 
template, a tempo di compilazione.
Piuttosto mi sarebbe piaciuto avere una ulteriore funzionalita:
le interface alla java,molto comode perchè non si eredita e quindi piu 
efficienti rispetto ad una classica ereditarieta.

 efficienti rispetto ad una classica ereditarieta.
Non mi pare che in C++ manchi tale funzionalita': basta definire una 
classe che contenga solamente funzioni pubbliche virtuali pure.


 efficienti rispetto ad una classica ereditarieta.
Invece a me non è mai piaciuto il fatto che in Java non ci fosse
l'ereditarietà multipla (e altre cose, tipo impossibilità di ridefinire gli
operatori, ma io parlo di vari anni fa, quando ancora non aveva nemmeno i
generics).

 alla nascita di sorgenti molto complessi.
Le tuple di cui sopra sono *gia'* implementate in boost.
Non mi sembra abbiano creato macelli fino ad ora.
Sono semplicemente la generalizzazione delle pairs che abbiamo gia'
nello standard.
Sono comode e non si usano piu' di tanto.
-- 
-riko

 capire il compilatore, senza che io glielo debba dire.
Ed e' una manna. :)
Presente quando hai da fare dei typedef solo per evitare tipi lunghi una
riga?
-- 
-riko

 efficienti rispetto ad una classica ereditarieta.
L'efficienza non centra una ceppa.
Oltretutto in Java paghi ovunque il "virtual", non puo' essere
altrimenti. Quindi non parlerei di efficienza: dove ci vuole il
polimorfismo dinamico s'ha da pagare e si paga. In C++ come in Java.
-- 
-riko

 In s� � chiaro ma se paragonato ad esempio all'uso delle tuple in python...
Grazie tante. :)
In Python e' tutto piu' semplice da scrivere e da leggere.
-- 
-riko

 In Python e' tutto piu' semplice da scrivere e da leggere.
Eheh, Python era l'esempio massimo, ma anche in altri linguaggi le tuple
sono più chiare, non dovendo specificare i tipi a priori.
Comunque, la mia filosofia è, meglio una caratteristica in più che una in
meno, poi chi vuole sceglie quella che preferisce.

 meno, poi chi vuole sceglie quella che preferisce.
La mia e' meglio una in meno che una in piu', il punto e' che le tuple
sono una cosa davvero comoda. 
-- 
-riko

Enrico Franchi ha scritto:

Il problema ï¿œ che tu dai il typedef e sei contento, ma poi il 
compilatore se ti dï¿œ un messaggio d'errore non ï¿œ cosï¿œ furbo da 
utilizzare il typedef, e ti presenta una dichiarazione lunga un 
chilometro...
E.

 pensavi?
Dicevo che Python è l'esempio massimo in generale, non relativamente alle
tuple.
Ma non è meglio dire tipizzato invece che tipato? :-D

 chilometro...
purtroppo. infatti io spero in auto...
-- 
-riko

 Ma non � meglio dire tipizzato invece che tipato? :-D
Possibile e probabile. Per lo meno e' una parola italiana. Odio
esprimermi in Italiano. 
-- 
-riko

 esprimermi in Italiano.
Io invece odio chi usa termini inglesi quando esistono adeguate 
traduzioni in italiano.
Va bene non essere puristi come i francesi o come qui in italia durante 
il fascismo, ma non esageriamo...
Ciao  Manlio

 traduzioni in italiano.
Io odio i termini inglesi italianizzati, ma addirittura odiare chi li
usa... ;-)
 

 traduzioni in italiano.
Ma sei sicuro che tipizzato, oltre ad esistere, sia la traduzione
corretta?
-- 
-riko

 
Non  e' proprio la stessa cosa dal punto di vista concettuale
e le funzioni virtuali difficilmente sono ottimizzabili inline

Enrico Franchi ha scritto:

Quando parlavo di efficienza parlavo di c++ , � ovvio che in java i 
metodi sono quasi sempre virtual (le classi final sono l' eccezione) e 
mai inline (o almeno non  mi risulta).
Quello che intendevo era il concetto di interfaccia come un espositore 
di metodi da implementare nella classe che implementa l' intefaccia.
Es di pseudo codice che implementa in c++ il concetto di interfaccia:
template <class T>
interface  myinterface    // implementa una interfaccia
	T operator++();  // il metodo da implementare
	...            // altri metodi
template <class T>
class  use_interface  : public /* sempre public */ fw_iter
	T operator++(); // use_interface deve implementare operator ++
template <class T>
inline void myf(const myinterface <T>& v) // funzione di esempio
E' chiaro che:
1) non c'e uso di  funzioni virtuali  e quindi il
compilatore puo espandere in linea  operator++ di use_interface
2) passando a myf un qualunque altro oggetto di una qualunque classe che
non implementa my_interface  si avrebbe un errore
(e questa e' l' utilita delle interfacce)
 
 

 generics).
quando, anni fa , appresi java lo paragonai al c++ (che gia conoscevo);
trovai interessante il concetto di interfaccia ma contemporaneamente
mi spiaccue  molto la mancanza della programmazione generica (e quella 
di oggi implementata in java non  è paragonabile come flessibilita ai 
template del c++), dell' overloading degli operatori della ereditarità 
multipla, nonchè il garbage collettor che ho sembre odiato (lo trovo 
assolutamente inutile e anche dannoso).
Comunque, si sa, i linguaggi perfetti per tutto non esistono :)

 (e questa e' l' utilita delle interfacce)
Peccato che siano implementate male.
Hai due classi di errori: la prima e' che hai un'interfaccia interamente
non-const e passi myinterface come const. Il che vuole dire che myf non
potrebbe fare legittimamente nulla. Per cui uccidiamo il const.
 Di fatto hai un "errore" anche quando passi un oggetto di tipo
my_interface.
Comunque, traduciamo il tuo codice in C++ vero:
#include <iostream>
template <typename T>
struct Incrementable {
    Incrementable<T>& operator++(); 
};
template<typename T>
Incrementable<T>& Incrementable<T>::operator++() {
    std::cout << "Called Incrementable::operator++()" << std::endl;
    return *this;
} 
template<typename T>
struct  Counter  : public Incrementable<T> {
    Counter<T>() : value() {}
    Incrementable<T>& operator++(); 
private:
    T value;
};
template<typename T>
Incrementable<T>& Counter<T>::operator++() {
    value++;
    return *this;
}
template <class T>
void myf(Incrementable<T>& v) {
    ++v;
}
int main() {
    Counter<unsigned long> c;
    myf(c);
}
Questo codice e' intrinsecamente sbagliato. In particolare deve essere:
template <typename T>
struct Incrementable {
    virtual Incrementable<T>& operator++(); 
    virtual ~Incrementable();
}; 
Ereditare da una classe il cui distruttore non e' virtuale e'
praticamente *sempre* un errore. Infatti se ti capita una cosa come
Base* b = new Derived();
...
delete b;
cosa piuttosto frequente, per inciso, vai a distruggere come Base, ma
non come Derived. Se Derived aveva allocato altre risorse, queste non
vengono distrutte.
-- 
-riko

 e le funzioni virtuali difficilmente sono ottimizzabili inline
Si, ma se non le usi quando fai polimorfismo dinamico ti trovi con dei
bachi.
-- 
-riko

 (e questa e' l' utilita delle interfacce)
Questo esempio non e' molto chiaro, ma e' chiaro che non esemplifica 
affatto "le interfacce alla Java". Somiglia invece ai "concetti", che 
verranno introdotti nel prossimo standard. In altre parole, non si 
tratta di polimorfismo a tempo d'esecuzione (cioe' quello delle funzioni 
virtuali), bensi' polimorfismo a tempo di compilazione (cioe' quello 
degli overload e dei template).
