:aie:
Version imprimable
:aie:
Pour creer un objet a partir d'une rvalue, il faut le copier, donc utiliser le constructeur de copie)Citation:
Envoyé par Charlemagne
(Note que la prochaine version de la norme aura des rvalue references qui n'auront pas cette exigence).
Pourquoi. La semantique de valeur -- ou la copie a du sens -- et une semantique de reference -- ou les virtuelles ont du sens -- vont generalement mal ensemble.Citation:
Je trouve pas que ce soit si courant que ça. En tout cas l'immense majorité des objets devrait être copiable.
La STL fournit essentiellement des classes ayant une semantique de valeur et sans virtuelles.Citation:
Dans la STL c'est le cas. (Toutefois par ex les streams ne sont pas copiables).
Visual serait-il alors en avance ? ( vision optimiste du bug )Citation:
Envoyé par Jean-Marc.Bourguet
Dans mon cas, je crois que ce serait plutôt lié à une ressource externe partagée, et qu'il faudrait sûrement introduire une notion de pointeur intelligent par exemple. ( enfin c'est l'idée que j'en ai, je ne suis pas un théoricien).Citation:
Envoyé par Jean-Marc.Bourguet
Mon objet à l'origine n'est pas copiable à cause d'un de ses membres qui ne l'est pas (un std::ostringstream justement).
Bref, si le constructeur de copie est visiblement exigé par le standard,ça serait pour une salade interne aux compilos, mais de toute évidence pas indispensable à tous les compilos.
(j'utilise rarement les fonctions virtuelles, dans mes calculs le polymorphisme statique par template est bien plus rapide)Citation:
Envoyé par Jean-Marc.Bourguet
Encore une fois: quel est le rapport entre le constructeur de copie et les fonctions virtuelles?
Pourquoi donc est-ce "rare d'avoir des classes copiables qui ont des fonctions virtuelles" ? certes un "constructeur de copie virtuel" (clone) est parfois nécessaire, mais ça n'empêche pas l'existence de constructeur de copie normal.
Et je ne pense pas que les streams ne sont pas copiables à cause des fonctions virtuelles qu'ils contiendraient mais plutôt à cause d'une sécurité pour éviter l'accès multiple à une ressource.
PS
Je crois pas que ce soit une bonne idée, puisque tu contournerais justement la sécurité. Mais ça dépend peut-être du contexte...Citation:
Envoyé par Hylvenir
Peut-être que tu peux sortir ta variable membre ostringstream de la classe...
C'était en effet l'idée pour éviter ce problème.Citation:
Envoyé par Charlemagne
Mais pour le moment, pas le temps. je fais avec.
Non, il y a une nouvelle syntaxe.Citation:
Envoyé par Hylvenir
Ce n'est pas une salade interne aux compilos, c'est une salade interne à la norme. Le langage est défini d'une certaine façon et certaines conséquences des règles sont parfois plus ou moins suprenantes. On peut après essayer d'introduire des exceptions, mais elles cassent la cohérence interne et ont tendance à produire en fait des résultats encore plus surprenant.Citation:
Envoyé par Charlemagne
Deux outils différents ayant des caractéristiques différentes. Il est des choses que l'un fait bien et que l'autre ne sait pas faire (vérifier statiquement les types, effectuer des choix dynamiques), et c'est généralement ces caractéristiques là plus que les perfs qui sont des critères déterminants.Citation:
(j'utilise rarement les fonctions virtuelles, dans mes calculs le polymorphisme statique par template est bien plus rapide)
Rien n'empeche dans le langage. Il y a même des cas où c'est utile. Mais en pratique ces cas sont rares. Ce lieu se prète mal à faire un cours de conception -- et je n'ai pas ni le temps ni réellement l'envie. Rapidement, on peut considérer qu'il y a deux types de classes: celles qui représentent des valeurs essentiellement immuables (même si pour la facilité on fournit parfois des membres qui modifient l'objet mais leur sémantique est essentiellement l'assignation d'une nouvelle valeur dérivée de l'ancienne), pour lesquelles la copie et l'égalité ont un sens et n'importe quel copie d'une valeur se comporte de la même manière; et celles qui représentent des entités mutables, pour lesquelles il n'y a pas réellement de notion d'égalité mais plutôt d'identité, où la copie n'a généralement pas de sens et quand elle en a il s'agit plutôt de création d'un nouvel objet ayant des attributs identiques à ceux de l'objet copiés mais sans qu'on considère qu'ils sont égaux -- il s'agit de ta fonction clone.Citation:
Encore une fois: quel est le rapport entre le constructeur de copie et les fonctions virtuelles?
Pourquoi donc est-ce "rare d'avoir des classes copiables qui ont des fonctions virtuelles" ? certes un "constructeur de copie virtuel" (clone) est parfois nécessaire, mais ça n'empêche pas l'existence de constructeur de copie normal.
Les fonctions virtuelles n'ont pas d'utilité dans le premier cas, parce que comme on manipule des objets par valeur, le type est fixé statiquement et donc il n'y a pas de dispatch. L'héritage même est pour ces types souvent un héritage d'implémentation qui serait théoriquement mieux privé.
Dans le second cas, on manipule des pointeurs et la copie est impossible car on ne connait souvent pas le type exact -- clone est possible parce qu'il retourne un pointeur.
Les streams ne sont pas copiables parce qu'elles sont des entités ayant un état et non des variables ayant une valeur.Citation:
Et je ne pense pas que les streams ne sont pas copiables à cause des fonctions virtuelles qu'ils contiendraient mais plutôt à cause d'une sécurité pour éviter l'accès multiple à une ressource.
Pour proposer une solution, il me faudrait comprendre le problème. Apparemment, il s'agit d'un problème de conception plus que d'un problème de C++ (j'ai du mal à voir pourquoi tu utilises une relation aussi forte avec quelque chose qui est une ressource externe).Citation:
Envoyé par Hylvenir
Allons-y gaiement...Citation:
Envoyé par Jean-Marc.Bourguet
Ma classe permet de formatter des messages
Le but étant de l'utiliser via des macros et une classe Log qui permet d'envoyer des messages formattés;Code:
1
2
3
4
5
6
7 struct Format { ostringstream buffer; Format( const char* msg ) { buffer << msg; } template<..>Format( const char* msg, const T& t ) { buffer << msg << t; } std::string str() { return buffer.str(); } };
Code:
1
2
3
4
5
6
7 #define DEBUG( MSG ) { Logger l; l.send( (MSG) ) ); } int main() { int a = 3; DEBUG( LogFormat( "Mon message", 3 ) ); }
peut être qu'un simple pointeur sur le stream pourrait faire une sorte de décoration...
Ici mon problème est que je dois donc faire :
en simplifiant en peu le tout.Code:
1
2
3
4
5
6 int main() { int a = 3; LogFormat lf("Mon message", 3 ); DEBUG( lf ); }
j'aurais dit qu'"une entité ayant un état" (qui peux changer) est synonyme de "variable" :?Citation:
Envoyé par Jean-Marc.Bourguet
:aie:
Ma proposition pour éviter d'avoir une stream en variable membre:Citation:
Envoyé par Hylvenir
-définir toi même ta classe stream de formatage
-surchargé l'opérateur <<
En fait de prendre modèle sur toutes les variations de streams de la STL.
ex:
Code:
1
2
3
4
5
6
7
8
9 class formated_stream { ... }; template<class T> formated_stream &operator<<(formated_stream &is, const T &x) { return is<<x; };
j'aurais aimé éviter ça.Citation:
Envoyé par Charlemagne
http://www.open-std.org/jtc1/sc22/op...6/special.html
J'ai trouvé sur les temporaires.
Avec sûrement une explication sur la nécessité du copy constructor.
C'est pourtant pas compliqué: si tu dérives ta classe de basic_ostringstream il ne suffit plus les opérateurs << qui doivent agir différemment d'un ostringstreamCitation:
Envoyé par Hylvenir
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 template <class E,class T=char_traits<E>,class A=allocator<E> > my_basic_ostringstream : public basic_ostringstream<E,T,A> { public: template<class X> explicit my_basic_ostringstream(const &X) : basic_ostringstream<E,T,A>(X) {} }; typedef my_basic_ostringstream<char> my_ostringstream; template<class E,class T,class A,class X> my_basic_ostringstream<E,T,A> &operator<<(my_basic_ostringstream<E,T,A> &os, const X &x) { basic_ostringstream<E,T,A> &oss=static_cast<basic_ostringstream<E,T,A> &>(os); oss<<x<<"blabla"; return os; }
Ce n'est pas une question de complexité mais plutôt de temps.Citation:
Envoyé par Charlemagne
Mais je vais regarder ta solution.
Merci.
D'autant plus que si ma mémoire est bonne, c'es io_base qui n'est pas copiable. donc ça ne change pas mon problème.
A vérifier toutefois.
Peut-etre un peu trop. Le ostringstream n'a aucune raison d'etre membre, il n'est utilise que dans les constructeurs. Une variable locale a ceux-ci serait mieux.Citation:
Envoyé par Hylvenir
Il est vrai que l'etat de l'entite peut parfois etre considere comme une valeur (et utiliser ce fait est meme un pattern du bouquin du GOF), mais je crains que j'essayais d'expliquer n'est pas passe, et j'ai pas le temps de reprendre ca ab initio. Effectue une recherche sur entite et valeur (peut-etre meme dans ce forum, le sujet a deja ete traite et ca ne m'etonnerais pas que Luc ou Loic ait poste des liens ou meme des explications pertinentes).Citation:
Envoyé par Hylvenir
Ok. Je comprends.Citation:
Envoyé par Jean-Marc.Bourguet
Je vais chercher.
Merci.
et stocker le résultat dans une std::string qui elle est copiable ?Citation:
Envoyé par Jean-Marc.Bourguet
La contrainte forte étant les performances.
mettre le stream en membre évitait de le construire plusieurs fois
mais en effet, il n'y a pas de raison.
Mais je vais essayer ce que tu proposes et mesurer ça.
Merci.