Afficher un message
Vieux 13/04/2008, 15h27   #6
James Kanze
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: initialiser variable constante dans le constructeur

On 13 avr, 15:39, Pascal Bourguignon <p...@informatimago.com> wrote:
> James Kanze <james.ka...@gmail.com> writes:
> > Fabien a montré la solution classique, mais il faut signaler que
> > s'il s'agit de plusieurs valeurs, dans une seule chaîne de
> > caractères, la solution est loin d'être optimale, parce qu'il
> > faudrait récréer la istringstream pour chaque valeur, sautant
> > les valeurs qu'on ne recherche pas chaque fois.


> Quel manque d'imagination!


Tu as oublié l'émoticon:-).

> class C
> {
> public:
> C(std::string const&);
> inline int getA(void) const {return a;}
> inline int getB(void) const {return b;}
> private:
> int const a;
> int const b;
> int getParameter(std::string const& arguments,unsigned int n);
> };


> C::C(std::string const& param)
> : a(getParameter(param,1)),
> b(getParameter(param,2))
> {}


> int C::getParameter(std::string const& arguments,unsigned int n){
> typedef std::map<std::string,std::vector<int> > ParameterCache;
> static ParameterCache cache;
> ParameterCache::iterator parameters=cache.find(arguments);
> if(parameters==cache.end()){
> std::istringstream in(arguments);
> std::vector<int> parsedArgs;
> while(not(in.eof())){


(Je sais que ta proposition est ironique, mais je tiens à
signaler en passant quand même qu'avec ce test, tu risques de
traiter un paramètre en trop, avec un comportement indéfini.)

> int argument;
> in>>argument;
> parsedArgs.push_back(argument);
> }
> cache[arguments]=parsedArgs;
> parameters=cache.find(arguments);
> }
> if(parameters->second.size()<=n){
> throw Error("Too few arguments");
> }
> return(parameters->second[n]);
> }


Avec une gestion d'erreurs correcte, des locks en plus si le
code est multi-thread, et assez de mémoire, effectivement, cette
solution pourrait marcher. Mais j'ai quand même comme une
impression que cette dernière considération va jouer contre elle
la plupart du temps.

> int main(void){
> C c0("0 1 2 3");
> C c1("10 11 12 13");


Tu aurais dû essayer:

C c3( "1\n" ) ;

Qui doit, je crois, provoque une erreur (mais qui ne le fait
probablement pas).

> std::cout<<"c0: "<<c0.getA()<<" "<<c0.getB()<<std::endl;
> std::cout<<"c1: "<<c1.getA()<<" "<<c1.getB()<<std::endl;
> return(0);
> }


> /*
> -*- mode: compilation; default-directory: "~/src/miscellaneous/tests-c++/"-*-
> Compilation started at Sun Apr 13 15:38:52


> g++ -o const-member const-member.c++ && ./const-member
> c0: 1 2
> c1: 11 12


> Compilation finished at Sun Apr 13 15:38:57
> */


Et maintenant, avec une boucle :

std::string line ;
while ( std::getline( std::cin, line ) ) {
C c( line ) ;
std::cout << getA() << ' ' << c.getB() << std::endl ;
}

Avec en entrée, un fichier avec des milliards de lignes
différentes.

On pourrait imaginer quelque chose de ce genre, avec, disons :

class C
{
static std::istringstream parser ;

C( std::string const& init )
: a( getFirst( init ) )
, b( getNext() )
{
parser >> std::ws ;
if ( ! parser || parser.get() != EOF ) {
throw uneErrorDeSyntax ;
}
}

static int getFirst( std::string const& init )
{
parser.str( init ) ;
int result ;
init >> result ;
return result ;
}

static int getNext()
{
int result ;
init >> result ;
return result ;
}
// ...
} ;

C'est quand même assez fragile (puisqu'il dépend de l'ordre des
initialisations), et évidemment, dès qu'il y a des threads...
(On peut aussi le rendre thread-safe, mais c'est encore plus
exotique.)

--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  Réponse avec citation
 
Page generated in 0,06566 seconds with 9 queries