Newsgroup: it.comp.lang.c++
Titolo: tellg

Considerate il seguente programma:
#include <fstream.h>
main()
{
  ifstream in("C:/config.sys", ios::in | ios::binary);
  int ch;
  unsigned long count= 0;
  unsigned long tot = 0;
  while(in)
  {
    ++tot;
    ch = in.get();
    if(ch != EOF) ++count;
  }
  cout << "tellg: " << in.tellg() << '\n';
  cout << "conteggio: " << count << '\n';
  cout << "tot: " << tot << '\n';
}
Con il BCC5.5 ottengo:
tellg: -1
conteggio: 251
tot: 252
mentre con il DJGPP
tellg: 251
conteggio: 251
tot: 253
Quale dei due compilatori si comporta meglio?
Che cosa specifica lo standard
( sia riguardo a while(in) che a tellg() )?

 ( sia riguardo a while(in) che a tellg() )?
tellg() deve tornare -1 (di tipo streampos) se e solo se fail() e`
true.  L'operator void*, che implicitamente e` usato dal tuo
while, torna 0 se e solo se fail() e` true.  Quindi gcc mi pare
qui fuori standard, perche` il while termina, quindi fail() deve
essere true, eppure tellg() non torna streampos(-1).
Alex

 wrote in message
8khobr$odc$1...@serv1.iunet.it...

Peccato, trovavo comodo l'uso di tellg() per sapere i byte letti.
Comunque non mi sembra del tutto corretto che tellg() fallisca
se č attivato il bit di eof.
La condizione eof non č proprio una condizione di errore
(almeno cosě la penso)
Saluti Manlio Perillo

 wrote in message 8ki975
| Comunque non mi sembra del tutto corretto che tellg() fallisca
| se č attivato il bit di eof.
| La condizione eof non č proprio una condizione di errore
| (almeno cosě la penso)
non la pensavano cosi' nel comitato standardizzatore, perche' hanno
scritto:
27.6.1.3 Unformatted input functions
[...]
3 int_type get();
Effects: Extracts a character c, if one is available. Otherwise, the
function calls setstate(failbit), which may throw ios_base::failure
(27.4.5.3),
^^^^^^^^^^^^^^^^^^^^^^
cioe' e' obbligatorio settare il failbit in caso non vi siano piu'
caratteri da leggere, mentre l'eccezione e' optional.

 (almeno cosě la penso)
Infatti non lo e`, il fatto che sia settato eofbit non implica
che lo sia failbit.  Ma il test while(in) non testa eofbit.  E
leggere quando eofbit e` settato causa il settaggio di failbit
(e questo mi pare sacrosanto!).
Testerai in.eof(), ovviamente, se ti interessa verificare
l'end-of-file senza causare failure!
Alex

 che tellg() debba fallire, incidentalmente
[...]
Scusa, mi sono espresso male.
Quindi alla fine, un modo per leggere il file come dico io è:
#include <fstream.h>
#include <cstdlib.h>
main()
{
  ifstream in("C:/config.sys", ios::in | ios::binary);
  int ch;
  unsigned long count= 0;
  unsigned long tot = 0;
  while(in)
  {
    ch = in.get();
    ++tot;
    if(ch != EOF) ++count;
    else
    {
      in.clear(ios::eofbit);
      goto end_of_file;
    }
  }
  cerr << "errore durante la lettura del file";
  exit(1);
  end_of_file:
  cout << "tellg: " << in.tellg() << '\n';
  cout << "conteggio: " << count << '\n';
  cout << "totale: " << tot << '\n';
}
Ottenendo con il BCC55:
tellg: 284
conteggio: 284
tot: 285
C'è per caso un modo migliore?
Inoltre un'ultima cosa (scusa se approfitto ma purtroppo non ho la
possibilità di consultare lo standard):
quando è che esattamente viene settato il bit di eof?
Grazie  Manlio Perillo

 quando è che esattamente viene settato il bit di eof?
Quando un estrattore (formattato o meno) incontra la fine-file
mentre cerca di estrarre (il che si riduce a rdbuf().in_avail()
che torna un valore <0, o rdbuf().underflow() che torna eof).
Le .get() di un singolo carattere non possono in pratica
trovarsi a settare eofbit; ma .get() multi-carattere, ad
esempio, setta eofbit se si trova ad estrarre meno di N
caratteri (il massimo numero richiesto) non perche` ha
trovato prima il carattere terminatore (di solito '\n')
ma a causa di un end-of-file (failbit invece e` settato
se non ha estratto _alcun_ elemento: questo e` quel che
succede quando il file termina con un '\n', alla prima
lettura immediatamente successiva all'estrazione di
quest'ultimo carattere).
Alex


[...]
Tutta questa mia curiosità scaturiva dal fatto che con il BCC5.5 ho
#include <fstream.h>
#include <cstdlib.h>
main()
{
  ifstream in("C:/config.sys", ios_base::in | ios_base::binary);
  int ch;
  unsigned long count= 0;
  unsigned long tot = 0;
  in.exceptions(ios_base::eofbit);
  try
  {
    while(in)
    {
      ch = in.get();
      ++tot;
      if(ch != EOF) ++count;
    }
    cerr << "errore durante la lettura del file";
    exit(1);
  }
  catch(ios_base::failure)
  {
    cout << "in.fail(): " << boolalpha << in.fail() << '\n';
    cout << "tellg: " << in.tellg() << '\n';
    cout << "conteggio: " << count << '\n';
    cout << "totale: " << tot << '\n';
  }
}
Output:
in.fail(): true
tellg: -1
conteggio: 284
tot: 284
Cioè il bit di fail è già settato quando si setta quello di eof.
Manlio  Perillo

 Cioè il bit di fail è già settato quando si setta quello di eof.
Ah, in questo senso chiedevi "quando".  Non lo so, non mi pare
che lo standard lo specifichi rigorosamente, ma mi pare che i
vari bit di stato siano concettualmente "settati in modo
simultaneo" (con una sola clear).  Vedro` cosa ha da dire in
merito il sacro testo di Langer, ma solo la settimana prossima
(l'ho lasciato al lavoro).
Alex

 Cioè il bit di fail è già settato quando si setta quello di eof.
Il bit di eof viene settato quando si tenta di leggere oltre la
fine del file (non quando si legge l'ultimo carattere).
Dopo aver letto l'ultimo carattere la situazione e':
  eof:  0
  fail: 0
la volta sucessiva get() tenta di leggere oltre la fine del
file (quindi setta eof) ma la lettura fallisce (quindi setta
anche fail), e la situazione diventa:
  eof:  1
  fail: 1
Spesso per gli stream di input eof e fail concidono, infatti
una delle cause principali di fallimento delle operazioni di
input e' la fine del file.
Esempio in cui eof e fail _non_ conicidono:
Il file di ingresso contiene:  12345<eof>
e si tenta di leggere un intero:
  int i;
  in >> i;
Durante la lettura dell'intero si raggiunge la fine del file
e si tenta di andare oltre (per vedere se ci sono altre cifre),
quindi viene settato eof.
La lettura pero' non e' fallita, c'e' un intero valido (12345)
e quindi fail non viene settato.
	Mauro

 (l'ho lasciato al lavoro).
Per Langer intendi il libro "Standard C++ IOStream and Locales"
by Angelica Langer & Klaus Kreft?
Come è?
Ne ho sentito parlare bene sul sito della ACCU, e stavo proprio cercando qualcosa
che mi permetesse di poter implementare un mio streambuffer.
Infatti vorrei implementare un iostream diretto su console usando le funzioni getch e
putch in conio.h;
in tal modo avrei un input interattivo, ad esempio get() non deve attendere la pressione
del tasto invio.
Vorrei poi implementare anche delle mie funzioni per effettuare il parsing di valori
numerici.
Altro mio progetto è di implementare un iostream diretto in una finestra di un ambiente
tipo Windows 98.
Nota: queste due idee mi sono venute perchè presenti, in parte, nel compilatore
della Borland C++ 5.02.
Veniva fornita la classe constream (ma senza il supporto per l'input);
inoltre con l'opzione EasyWin era possibile redirigere lo standard input ed output
in una finestra Window (ma solo per Windows 3.1, inoltre non era implementata una
iostream).
Non ho mai capito perchè alla Borland non abbiano perfezionato queste due idee,
vista l'enorma flessibilità che offre lo stream del C++.
Comunque, a parte queste mie note personali, il testo della Langer mi fornirebbe adeguato
supporto per quello che intendo fare?
Grazie  Manlio Perillo

 supporto per quello che intendo fare?
Si`, ma penso che basti Josuttis, e personalmente lo trovo molto piu`
leggibile e scorrevole.
Alex


Ovviamente,  io intendevo usando il locale.
Grazie  Manlio Perillo

 Ovviamente,  io intendevo usando il locale.
Sorry, mi era sfuggito l'"ovviamente"!-)
Alex

supporto a chi volesse usarlo.
Onestamente sono 10 anni che non uso il goto e fino ad ora non ne ho
sentito la mancanza... Dubito che ci siano casi in cui il goto sia
necessario (nel contesto di un linguaggio come il C++) e che non ci
siano metodi piu` "puliti".
Paolo

 wrote in message
news:odo6nsk6lunj2tioj...@4ax.com...

Il discorso del "necessario" e "piu` puliti" vale praticamente in qualsiasi
linguaggio; Jacopini e Boehm ci hanno mostrato da un pezzo (1966?)
come qualsiasi diagramma di flusso possa essere riscritto con if e while
*e sole trasformazioni locali* (senza quest'ultimo vincolo, il teorema
sarebbe poi addirittura banale nella sua ovvieta`).
Il problema, dunque, non e` il "necessario", bensi` l'"opportuno".
Un buon riassunto e` in un capitolo di Code Complete in linea a:
http://www.construx.com/stevemcc/ccgoto.htm
Eccetto che McConnell parla sostanzialmente del linguaggio *C*
(e altri linguaggi di quella generazione), NON del C++.  Non so
bene cosa tu intenda in questo contesto con "un linguaggio come
il C++", se non, esattamente, il C++ stesso.  Dopo tutto, in Java,
ad esempio, il goto non esiste proprio, per cui e` difficile che ci si
trovi a dibattere sulla sua necessita` (o opportunita`), se non per il
gusto di fare "l'avvocato del diavolo" come fa appunto Bezroukov
in 
http://www.softpanorama.org/Lang/Java/Tijplus/tijplus03.shtml
(con affermazioni come "Java e` una versione migliorata di Visual
Basic, non certo di C++", studiate accuratamente per fare alzare la
pressione del sangue ai veri appassionati di Java... o di VB!-).
McConnell identifica gli usi *opportuni* del goto sostanzialmente
in quelli connessi alla gestione degli errori, e in particolare alla
garanzia che il codice per deallocare risorse esista in una sola
copia.  Ma il C++ per questi scopi fornisce le exception ed i
distruttori, che, nell'idioma "resource allocation is construction",
raggiungono lo stesso scopo in modo assai piu` vantaggioso (Java,
i cui finalize non sono equivalenti a distruttori, fornisce try/finally,
oltre alle exception, per lo stesso scopo).
Se non fosse per le exception, goto resterebbe *opportuno* (per
certe strategie di gestione degli errori) benche` non *necessario*.
E` _importante_ per la leggibilita` e la chiarezza di un programma
non mescolare il codice di gestione di errore al flusso principale di
esecuzione nei casi normali.  In un programma professionale, non e`
insolito che due terzi del codice riguardino casi eccezionali -- la loro
estrema rarita` non esime il programma dalla necessita` di reagire
in modo solido, prevedibile, e ragionevole, se e quando succedono.
Se tutti questi "distinguo" sono mischiati "in linea" con il codice
"normale", quest'ultimo finisce per essere "affogato" dal codice
"anormale", quello che non viene eseguito quasi mai.  E` la via
maestra per rendere illeggibile e inmanutenibile un programma!-)
Questo non vuol dire che le exception siano *facili* da usare BENE.
Raccomando caldamente la lunga e dettagliata serie di articoli di
Robert Schmidt su questo tema, leggibile a partire da (1 sola URL):
http://msdn.microsoft.com/library/default.asp?URL=/library/welcome/dsmsdn/de
ep051099.htm
Ma sono INDISPENSABILI.... per avere codice pulito, leggibile,
senza goto, _E_ professionalmente solido nella sua risposta agli
errori piu` vari che possano mai verificarsi!-)
Alex

 siano metodi piu` "puliti".
Come mi è capitato di dire altre volte, io in Clipper sono quindici anni
che non uso il goto. Infatti Clipper non ha il goto e non c'è alcun
motivo per desiderarlo. Però, come il C++, ha le eccezioni.
EMG

il C++", se non, esattamente, il C++ stesso
Piu` banalmente un qualsiasi linguaggio di alto livello che disponga
di if e while (o equivalenti che non comprendano il goto) e magari
delle eccezioni (per il tuo discorso sull'opportuno).
Paolo

motivo per desiderarlo. Però, come il C++, ha le eccezioni.
Ma io nei 10 anni non ho usato solo il C++, ma anche altri linguaggi
che le eccezioni non le avevano (o hanno)!    :o
Paolo

 wrote in message
news:c3n9nssl7npgat9s1...@4ax.com...

E allora, o non facevi una gestione rigorosa di tutti gli
infiniti possibili (benche` rarissimi) errori, oppure la facevi
"spargendone" il codice (che, a braccio, dovrebbe essere
non meno di quello che gestisce i casi normali; dipende
anche dal tuo ambito applicativo) in totale mistura con
il codice del flusso principale di esecuzione, oscurando
quest'ultimo e rendendone piu` difficile l'evoluzione futura.
Un esempio tipico, un poco astratto.  Devo acquisire tre
risorse A, B, e C; ciascuna risorsa, se acquista con successo,
DEVE essere rilasciata (ma non dev'essere rilasciata se non
acquisita!-); se acquisisco tutte le risorse, passo poi
all'elaborazione X.
All'osso, senza exception ne` goto, la struttura:
    A a;
    if(getA(&a)) {
        B b;
        if(getB(&b)) {
            C c;
            if(getC(&c)) {
                if(X(&a,&b,&c)) {
                    /* tutto OK! */
                } else {
                    error("fallita X");
                }
                riliasciaC(&c);
            } else {
                error("non becco C");
            }
            rilasciaB(&b);
        } else {
            error("non becco B");
        }
        rilasciaA(&a);
    } else {
        error("non becco A");
    }
Questo e` un buon esempio di struttura ingestibile a medio
termine.  Nonostante la sua regolarita`, il puro e semplice
annidamento *nasconde* il codice vero/normale.
In C++, con costruttori/distruttori ed eccezioni:
    try {
        smartA a;
        smartB b;
        smartC c;
        X(&a, &b, &c);
    } catch(const exception& ex) {
        error(ex.what());
    }
con le varie classi
    struct smartA: public A {
        smartA() {
            if(!getA(this)) throw exception("non becco A");
        }
        ~smartA() {
           rilasciaA(this);
        }
    };
E questa e` sicuramente la strada migliore.  Ma se usi un linguaggio
tecnologicamente povero, il meglio che puoi fare per imitarla e`:
    A a;
    if(!getA(&a)) { error("non becco A"); goto dopoA; }
    B b;
    if(!getB(&b)) { error("non becco B"); goto dopoB; }
    C c;
    if(!getC(&c)) { error("non becco C"); goto dopoC; }
    if(X(&a,&b,&c)) {
        /* tutto OK! */
    } else {
        error("fallita X");
    }
    rilasciaC(&c);
dopoC:
    rilasciaB(&b);
dopoB:
    rilasciaA(&a);
dopoA:
Questa ha in comune con la struttura ad exception una discreta
linearita` di esecuzione del codice normale; si evita l'eccessivo
annidamento.
Se hai i costruttori e i distruttori ma non le exception, puoi fare
un compromesso, tipicamente associando ad ogni "smartA"
ecc un flag che dice se l'acquisizione nel costruttore e` andata
a buon fine; ma la struttura di controllo preferibile resta quella
a goto (se supportata dal linguaggio...):
    smartA a;
    if(a.fallito()) goto fuori;
    smartB b;
    if(b.fallito()) goto fuori;
    smartC c;
    if(c.fallito()) goto fuori;
    if(X(&a,&b,&c)) {
        /* tutto OK! */
    } else {
        error("fallita X");
    }
    fuori:
Questo, in C++, non e` ammesso (il goto interferisce con i
costruttori) e quindi occorre un qualche trucco equivalente,
tipo (classico idioma del C++ prima delle exception...):
    do {
        smartA a;
        if(a.fallito()) break;
        smartB b;
        if(b.fallito()) break;
        smartC c;
        if(c.fallito()) break;
        if(X(&a,&b,&c)) {
            /* tutto OK! */
        } else {
            error("fallita X");
        }
    } while(false);
Questo "ciclo che non e` un ciclo" non e` certo leggibilissimo,
ma, pazienza, ci si abitua.  Se non altro e` esattamente
altrettanto lineare della versione a goto teste` presentata,
e la rimozione del codice di acquisizione e rilascio dal
flusso principale resta comunque un'ottima cosa.
Quando il "fallimento di acquisizione" *NON* e` una
circostanza eccezionale, ma invece ha buona frequenza,
probabilmente questo e` ancora il meglio che si possa
fare in C++.  E` importante NON usare le exception
in circostanze NON eccezionali, solo per simulare la
presenza nel linguaggio di strutture di controllo ricche
che in realta` gli mancano!-)
Alex

 wrote :
[tutta la solfa su goto ed eccezioni ;-]
una cosa che mi sono sempre chiesto:
1 - alcune exception usano per il what() le std::string,che
    potrebbero allocare memoria dinamica.
2 - se la memoria si esaurisce, viene generata un'eccezione.
Come si comporta il programma, se l'eccezione sollevata per mem. esaurita
alloca memoria?
Nello std non ho trovato nulla al riguardo, essendo (credo) tutta roba
implementation defined, ma forse sbaglio...

 implementation defined, ma forse sbaglio...
Non ne sono sicuro, ma mi pare che, in generale, qualsiasi sia
il tipo di ritorno di funz(), nel costrutto:
    throw funz();
se funz genera un'eccezione, quella parte, e il throw che STAVA
per avvenire non avviene piu`.  Il caso che tu menzioni mi pare un
caso particolare di questo, dove funz() e` il costruttore di una
qualche classe derivata da std::exception.
Alex

 wrote:
[...]
| Se l'eccezione di manca-memoria avviene durante la costruzione
| dell'eccezione che stai cercando di lanciare, il throw non dovrebbe
| venire neppure eseguito; c'e` solo la std::bad_alloc.
Non dovrebbe chiamare terminate()? (15.5.1)
Comunque, per evitare questo, ma solo se si corre il rischio di una
mem_exception, uso un artifizio basato sul fatto che:
1 - una stringa passata con static object duration, permette di ricordarne
semplicemente l'indirizzo, senza allocare mem
2 - un template accetta un puntatore a carattere come *parametro* solo se
ha static duration
extern const char p[] = "stringa" ;
template< char* p > class X {
  //...
};
X< p > x1;          // questo e' corretto
X< "Messaggio"> x2; // questo no.
(si veda il punto 14.3.3)
ecco qua la classe:
template <const char* stringa_>
class MemorySafeException : public std::exception {
/* std::exception non solleva eccezioni (18.6.1.3) */
public:
  const char * what() const throw(){
    return stringa_;
  }
};
non so come si comporta la std::exception, essendo virtuale quasi pura,
dovrebbe essere abbastanza sicura di per se', visto che inoltre non solleva
eccezioni.
Poi da questa mi derivo le varie eccezioni, tutte con data object statici.
E' abbastanza sicuro, o mi sfugge qualcosa?

 mem_exception, uso un artifizio basato sul fatto che:
Certo, non e` difficile evitare il "rischio" (di una std::bad_alloc; non
so cosa sia una mem_exception?), basta esserne coscienti.
Secondo me, comunque, l'unica cosa che vale veramente qualsiasi
costo evitare e` un'exception *in un distruttore*.  Quella non
ti da` necessariamente segnalazioni comprensibili ma causa tanti
di quei potenziali danni che non si finisce piu`...
Alex

tecnologicamente povero, il meglio che puoi fare per imitarla e`:
bool Result = true;
A a;
if(!getA(&a)) { error("non becco A"); RilasciaA; result = false; }
B b;
if(Result && !getB(&b)) { error("non becco B"); .... }
e si elimina il goto esplicito.
In turbo pascal c'era un embrione di paradigma OO che
in qualche modo aiutava.
Naturalmente cio` non toglie che disporre delle eccezioni e`
di gran lunga migliore, anche per questo passai al C++.
Paolo

alloca memoria?
Infatti la classe std::string non e` exception safe!
Su C++Informer la newsletter di Pescio tempo fa si parlo` della cosa
e di possibili approcci al problema.
Paolo

 e si elimina il goto esplicito.
Si, ma si altera la semantica, rendendola errata.  A va rilasciata
se e solo se e` stata acquisita; questa la rilascia se NON e`
riuscita ad acquisirla, e alla fine non puo` piu` sapere se
deve rilasciarla o meno.
La variabile di stato che devi portarti dietro, e testare ad
ogni passo, e` quindi molto piu` complessa di un bool: e` un
vettore di tre bool, che devi testare singolarmente ma anche
collettivamente.  Certo, puoi crittare la terna in un intero
su cui operare con operazioni bitwise di mascheramento.
In pratica, sei al livello del "pseudo-Jacopini-Boehm": per
convertire un diagramma di flusso arbitrario senza l'uso di
goto, numera ciascun blocco, aggiungi una variabile di stato,
e simula la macchina-con-goto che esegue direttamente la
struttura del diagramma di flusso, eseguendo ad ogni passo
il blocco di codice corrispondente al numero dello stato
attuale e, per simulare il goto, settando la variabile di
stato al numero del blocco successivo.  Il tuo approccio
non ha questa piena generalita`, perche` il loop e` unrolled
e ciascuno switch puo` essere collassato in una sequenza
di uno o piu` casi a due vie.
Naturalmente, queste pseudo-semplificazioni non portano
nessun vantaggio, anzi.  Il programma che ne risulta e`
assai piu` complesso da comprendere e manutenere, oltre
che meno efficiente (tutte le operazioni del flusso
normale devono essere precedute dal controllo "se e`
ancora tutto a posto sin qui"), della semplicissima
versione basata su goto, la quale, in cambio, non ha
*nessuno* svantaggio rispetto a questo approccio. Se
non, ovviamente, quello di dovere continuamente entrare
in litigi contro i fanatici anti-goto.
E` proprio contro queste assurde contorsioni allo scopo
feticistico di eliminare i goto, che mi faccio quattro
risate in un brano del mio tutorial di programmazione
Win32.  Nulla di originale, ovviamente, visto ad esempio
che Donald Knuth, uno dei piu` grandi programmatori e
teorici del nostro settore, se le faceva a meta` anni
'70 ("Structured programming WITH goto statements", un
articolo che dovrebbe essere obbligatorio leggere e
capire per potere parlare di programmazione).
Con uno da una parte, che usa un goto in un caso in
cui non ce n'e` nessun bisogno *e lo difende con la
scusa che il C++ e` multi-paradigma*, e uno dall'altra,
che apparentemente considera pessime strutture come
quella teste` discussa preferibile al normale uso dei
goto per la gestione di errori (in ambienti privi di
exception), mi sento perfettamente a mio agio: nel
giusto mezzo, accanto a Knuth, a difendere l'uso del
goto per la SOLA gestione d'errore (in linguaggi privi
di exception).  [NB: gli altri casi previsti da Knuth
sono ovviati dall'esistenza di break/continue generali
come in Java, ma *non* al 100% (solo al 99%) da quelli
meno generali presenti in C++].
Alex

 wrote
| Infatti la classe std::string non e` exception safe!
| Su C++Informer la newsletter di Pescio tempo fa si parlo` della cosa
| e di possibili approcci al problema.
Cos'e' sta roba? Pescio non e' quello di CP?

 wrote in message
|
| Quale dei casi di 15.5.1 avevi in mente?
cito:
15.5.1 The terminate() function
1 In the following situations exception handling must be abandoned for less
subtle error handling techniques:
[...]
- when unexpected throws an exception which is not allowed by the
previously violated exception貞pecification, and std::bad_exception is not
included in that exception貞pecification (15.5.2), or
questo in particolare mi sembra faccia riferimento a casi in cui
un'eccezione possa generare un'altra eccezione.
| non so cosa sia una mem_exception?), basta esserne coscienti.
Abbreviazione per eccezione di manca-memoria fatta in casa e di corsa!-)
| Secondo me, comunque, l'unica cosa che vale veramente qualsiasi
| costo evitare e` un'exception *in un distruttore*.  Quella non
| ti da` necessariamente segnalazioni comprensibili ma causa tanti
| di quei potenziali danni che non si finisce piu`...
C'era un collega che aveva proposto una soluzione... se la ritrovo, la
posto.

 Abbreviazione per eccezione di manca-memoria fatta in casa e di corsa!-)
Ah, std::bad_alloc, dunque?
Alex

 wrote :
[...]
| Certo, se il costruttore di pippo dicesse "throws()" cambierebbe
| tutto.  Ma dove lo dice?
Non ci siamo capiti: io dicevo proprio nel caso in cui un'eccezione (che ha
throws() nel costruttore, come molte delle std::XXX), solleva un'eccezione.
Non e' quello il caso del par. che ho riportato?
Abbiamo un prog. che genera un'eccezione, poniamo derivata std::bad_alloc,
con un throws() nel costruttore, da brava eccezione. Se questa mi alloca
memoria, che e' gia' esaurita, e solleva dunque una std::bad_alloc, non
viene chiamata la terminate()? o si entra in un circolo vizioso, con
l'eccezione che genera un'eccezione che genera....?
| > Abbreviazione per eccezione di manca-memoria fatta in casa e di
corsa!-)
|
| Ah, std::bad_alloc, dunque?
si. Per chiarezza (non raggiunta, ovviamente) avevo scritto cosi'.

in litigi contro i fanatici anti-goto.
Sappiamo benissimo che il problema non e` il goto, ma
l'uso che se ne fa... Io ho scelto la strada di evitarlo per
non farmi prendere la mano (chiamala "defensive
auto-programming":)
Paolo

Cos'e' sta roba? Pescio non e' quello di CP?
Si, per maggiori info, ti rimando al suo sito
www.eptacom.net
 (mi pare).
Paolo

 auto-programming":)
Immagino che siano in effetti problemi soggettivi.  Io non
corro nessun rischio a tenere in casa chili di liquirizia: non
mi piace, se per qualche ragione devo prenderne una
pastiglia al giorno non mi prendera` certo la mano.  E`
invece un rischio che io tenga in casa eccellenti pasticcini
allo zabajone: *potrei* soccombere alla tentazione di
divorarne una quantita` eccessiva, perche` mi piacciono
davvero troppo.
Il goto non mi piace.  Non corro alcun rischio di farmi
prendere la mano, come non lo corro per la liquirizia.
Lo uso "se me lo prescrive il medico", cioe` quando so
per dura e lunga esperienza che "mi fa bene", ovvero, se
preferisci, "e` il male minore".
Il rischio che SO di correre (e non conosco _alcun_
programmatore che non lo corra) e` di farmi prendere
la mano dalla *furbizia* eccessiva, facendo strutture
faraoniche, di cui non c'e` vera necessita`, perche` sono
intrinsecamente belle, o perche` penso che magari un
domani quella generalita` mi aiutera` (9 su 10, invece,
resta li`, non sfruttata), ecc, ecc.  *SEMPLICITA`*
e` dunque quello che mi devo auto-imporre con
Alfieriana fermezza.  In mancanza di exception (che
siamo tutti d'accordo essere la cosa migliore, _se e
quando_ correttamente applicabili), il goto tende ad
essere la soluzione piu` semplice e vantaggiosa *per lo
specifico scopo di gestire gli errori*.
Per il problema dell'uscita annidata, in mancanza di
break multi-livello (sigh), la soluzione piu` semplice
tende ad essere quella di frammentare i loop annidati
in una funzione separata (con return da dentro tutto
il nido).  Ma questo generalmente de-localizza stato
che altrimenti avrebbe potuto essere locale ad una
singola procedura, quindi ogni tanto i goto possono
anche qui risultare il male minore.  (Oppure passare a
Java, che i break multi-livello li ha:-).
Non conosco altri casi.
Alex

 l'eccezione che genera un'eccezione che genera....?
Non mi sembra che il caso sia quello che stiamo discutendo, ma
forse ricordo solo male <stdexcept>, controllero`.   Se questo caso
si verifica, comunque, terminate() e` garantita.
Alex


| Si, per maggiori info, ti rimando al suo sito
| 
www.eptacom.net
 (mi pare).
E' corretta, grazie.

Non conosco altri casi.
E a me onestamente non ne sono capitati molti, ed
in quelle poche situazioni sono riuscito a cavarmela senza
goto. Fortuna? Forse!
Paolo

 goto. Fortuna? Forse!
Forse invece diverso livello di tolleranza per prassi, a mio
vedere, _intollerabili_ (ripetizione di codice, oscuramento del
flusso principale di esecuzione, ecc ecc) ammesso che la
gestione degli errori fosse sempre "certosina e paranoica"
quanto, in un'applicazione professionale, dovrebbe essere.
Alex