Newsgroup: it.comp.lang.c++
Titolo: STL e template

Perchč se provo a compilare questo programma mi dice "no copy constructor
available"? E' possibile che le STL non funzionino con classi contenenti
template??
#include <list>
using std::list;
template <class T>
class prova
{
 T ciao;
public:
 prova() {};
 prova(prova& rhs) {};
};
int main()
{
 list<prova<int> > lista;
 prova<int> p;
 lista.push_back(p);
 return 0;
}

  prova(prova& rhs) {};
Qua devi scrivere:
 prova(const prova& rhs) {};
Ciao
Maurus

 Perchè se provo a compilare questo programma mi dice "no copy constructor

Il compilatore, come sempre (quasi), dice il vero: la tua classe
prova non ha il costruttore di copia definito.
Data una classe T il costruttore di copia ha la seguente signature:
T(const T&);
ti sei scordato il const insomma!!!
Ciao
Gaetano

 T(const T&);
Sul Lippman c'è scritto (pag. 688):
"Il parametro del costruttore di copia non dev'essere necessariamente
const,..."
Sbaglia il libro oppure la richiesta del const è specifica per poter
inserire oggetti nei contenitori?
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

 inserire oggetti nei contenitori?
La seconda. Vedi 20.1.3 - Copy construction [lib.copyconstructible]
Max

 wrote in message
news:6b0ab1c2.0304...@posting.google.com...

Dallo
INTERNATIONAL
STANDARD
ISO/IEC
14882
12.1.10:
A copy constructor for a class X is a constructor with a first parameter of
type X& or of type const X&.
[Note: see 12.8 for more information on copy constructors. ]
12.8.2:
A nontemplate
constructor for class X is a copy constructor if its first parameter is of
type X&, const X&,
volatile X& or const volatile X&, and either there are no other parameters
or else all other
parameters have default arguments (8.3.6).106)
Ciao
Gaetano

 inserire oggetti nei contenitori?
Secondo lo standard un costruttore di una classe C e' un costruttore
di copia se il primo parametro e' di uno tra i tipi: C &, C const &, C
volatile &, C const volatile & e non ci sono altri parametri oppure
tutti gli altri parametri hanno un valore di default.
Ciao,
Nicola

 La seconda. Vedi 20.1.3 - Copy construction [lib.copyconstructible]
Grazie.


 tutti gli altri parametri hanno un valore di default.
Infatti questo era quello che sapevo. Ma allora non capisco perché
l'esempio di aiscrim
#include <list>
using std::list;
template <class T>
class prova
{
 T ciao;
public:
 prova() {};
 prova(prova& rhs) {};
};
int main()
{
 list<prova<int> > lista;
 prova<int> p;
 lista.push_back(p);
 return 0;
}
non compila né con Borland C++ 5.5.1 né con DJGPP (una versione non
recente). Ma compila se si mette il const nel costruttore di copia.


 recente). Ma compila se si mette il const nel costruttore di copia.
Il motivo č illustrato in quel passo dello Standard che citavo.
  20.1.3 Copy construction [lib.copyconstructible]   
  In the following Table 30, T is a type to be supplied by a C ++ program
  instantiating a template, t is a value of type T, and u is a value of 
  type const T.
  Table 30 - CopyConstructible requirements
   expression  return type  requirement
   T(t)                     t is equivalent to T(t) 
   T(u)                     u is equivalent to T(u) 
Poichč u č un 'const T', 'T(u)' compila soltanto se esiste un copy-ctor che 
accetti un 'const T&'.
Max

 accetti un 'const T&'.
Credo di aver capito. Dato che il metodo
void std::list::push_back(const T&);
richiede un const T & allora c'č bisogno del costruttore di copia con
parametro const T &. Ho detto bene o sono ancora fuori strada?


 parametro const T &. Ho detto bene o sono ancora fuori strada?
Esatto. Il valore che passi e' costante all'interno della funzione e
quindi non puoi prenderne un reference non const.
Ciao,
Nicola

 quindi non puoi prenderne un reference non const.
Ma allora non capisco perché il seguente codice funziona:
#include <iostream>
class ClassA
{
    public:
        ClassA() {}
        ClassA( ClassA & ) {}
        const char *ClassName() const { return "ClassA"; }
};
class ClassB
{
    public:
        void Function( const ClassA &a ) const
        {
            std::cout << a.ClassName() << '\n';
        }
};
int main()
{
    ClassA a;
    ClassB b;
    b.Function( a );
    return 0;
}
Che c'è di diverso, che mi sfugge, tra questo e l'esempio di aiscrim?


 
Superficialmente niente. Ma nel tuo codice il copy-ctor non viene mai
usato, mentre nella push_back di un container l'oggetto viene
presumibilmente copiato, e giacché l'argomento della funzione è un
const-ref, serve un copy-ctor che accetti un oggetto const.
A dire il vero, la presenza di quel ctor è richiesto dallo Standard,
ma non è impossibile scrivere, ad esempio, un std::vector che usi
soltanto il ctor di default e l'operatore assegnamento.
Max

 Che c'è di diverso, che mi sfugge, tra questo e l'esempio di aiscrim?
Spero di essere stato esauriente.
Ciao,
Nicola

 const-ref, serve un copy-ctor che accetti un oggetto const.
Giusto! Ecco allora il mio esempio modificato che ora finalmente dà
errore:
#include <iostream>
class ClassA
{
    public:
        ClassA() {}
        ClassA( ClassA & ) {}
        const char *ClassName() const { return "ClassA"; }
};
class ClassB
{
    public:
        void Function( const ClassA &a ) const
        {
            ClassA tmp( a );  // Copia
            std::cout << a.ClassName() << '\n';
        }
};
int main()
{
    ClassA a;
    ClassB b;
    b.Function( a );
    return 0;
}
Grazie.


 Spero di essere stato esauriente.
Sģ, ti ringrazio.
