Note: ma question n'est pas directement lié à l'API Windows, ou à la
gestion des threads (quand j'en parle, c'est pour expliquer le contexte)
Je désire utiliser la fonction "OutputDebugString(char*)" de Windows
(envoie la chaine de caractères en paramètre au débugger) à travers un
"ostream" pour bénéfier des capacités de formatage. J'ai trouver sur les
net des classes héritant de "streambuf" effectuant cette tache. Elles
s'utilisent de façon suivante:
Je ne suis pas sur que la conception des "ostream" permette une
utilisation en multi-thread (sans mutex), donc je voudrais donc créer
mes "ostream" spéciaux en temps que variable locale. Le problème est que
c'est tout de même assez verbeux d'avoir à chaque fois trois lignes pour
sortir du debug. La solution suivante (pseudo code) ne marche pas:
class dbg_stream:public std::ostream
{
dbg_stream : std::ostream(m_buff)
custom_buf m_buff;
};
car le constructeur de "ostream" va utiliser un objet "custom_buf" non
initialisé.
Sinon, j'avais pensé à ça (mettez ce que vous voulez à la place de
l'operateur parenthèse: un opérateur *, une fonction):
class Toto
{
public:
Toto():m_Stream(&m_Buff){}
std::ostream& operator()(){ return m_Stream; }
private:
ods_tstreambuf m_Buff;
std::ostream m_Stream;
};
Toto()() << 123 << "aaa";
Sauf que je trouve la notation "Toto()()" laide. Mais je ne vois pas
comment faire plus court (à moins d'utiliser un #define...).
A+ -- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Fabien SK <fabsk+news@free.fr> writes:
[initialisation d'in ostream]
La solution suivante (pseudo code) ne marche pas:
class dbg_stream:public std::ostream
{
dbg_stream : std::ostream(m_buff)
custom_buf m_buff;
};
car le constructeur de "ostream" va utiliser un objet "custom_buf" non
initialisé.
Voir la FAQ pour une solution utilisant l'heritage prive. Une autre
est d'utiliser le membre init.
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
A+ -- Jean-Marc FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html Site de usenet-fr: http://www.usenet-fr.news.eu.org
Fabien SK
Jean-Marc Bourguet wrote:
Fabien SK <fabsk+ writes:
[initialisation d'in ostream]
Voir la FAQ pour une solution utilisant l'heritage prive. Une autre est d'utiliser le membre init.
Merci (je suis une quiche vraiment, j'ai tenté d'utilisé le bout de code telle quel sans voir les possibilités qu'offre la classe ostream)
Fabien SK
On Fri, 12 Sep 2003 07:06:59 -0700, kanz wrote:
Je ne suis pas sur que la conception des "ostream" permette une utilisation en multi-thread (sans mutex),
Ce n'est pas spécifié par le langage. La pensée moderne, c'est que la gestion des mutex dans les flux, c'est d'un niveau trop bas. (Dans ton cas, par exemple, il permettrait à un autre thread d'intercaler des données entre le 123 et le "aaa".) Je m'attendrais donc à avoir besoin d'un mutex dans mon code.
Je ne connais pas beaucoup les streambuf et ostream (ah si j'avais le temps pour tout), mais j'imagine que la manipulation des pointeurs dans le buffer du streambuf peut amener à des choses bien pire (un pointeur trop incrémenté et qui amène à lire en dehors du buffer) => boom
Merci beaucoup pour ta réponse
On Fri, 12 Sep 2003 07:06:59 -0700, kanz wrote:
Je ne suis pas sur que la conception des "ostream" permette une
utilisation en multi-thread (sans mutex),
Ce n'est pas spécifié par le langage. La pensée moderne, c'est que la
gestion des mutex dans les flux, c'est d'un niveau trop bas. (Dans ton
cas, par exemple, il permettrait à un autre thread d'intercaler des
données entre le 123 et le "aaa".) Je m'attendrais donc à avoir besoin
d'un mutex dans mon code.
Je ne connais pas beaucoup les streambuf et ostream (ah si j'avais le
temps pour tout), mais j'imagine que la manipulation des pointeurs dans le
buffer du streambuf peut amener à des choses bien pire (un pointeur trop
incrémenté et qui amène à lire en dehors du buffer) => boom
Je ne suis pas sur que la conception des "ostream" permette une utilisation en multi-thread (sans mutex),
Ce n'est pas spécifié par le langage. La pensée moderne, c'est que la gestion des mutex dans les flux, c'est d'un niveau trop bas. (Dans ton cas, par exemple, il permettrait à un autre thread d'intercaler des données entre le 123 et le "aaa".) Je m'attendrais donc à avoir besoin d'un mutex dans mon code.
Je ne connais pas beaucoup les streambuf et ostream (ah si j'avais le temps pour tout), mais j'imagine que la manipulation des pointeurs dans le buffer du streambuf peut amener à des choses bien pire (un pointeur trop incrémenté et qui amène à lire en dehors du buffer) => boom
Merci beaucoup pour ta réponse
Samuel Krempp
le Friday 12 September 2003 16:06, écrivit :
class dbg_stream : public std::ostream, private virtual std::custom_buf { dbg_stream() : std::ostream( this ) ... } ;
boost/utility/base_from_member.hpp a été fait exprès pour ce cas :
class dbg_stream : private boost::base_from_member<custom_buf >, public ::std::basic_ostream<CharType, CharTraits> { ...
c'est un détail, mais ça fait pile ce qu'on veut : 1. l'héritage privé assure la priorité du construction du buf. 2. le buf est accessible par this->pbase_type::member (avec typedef boost::base_from_member<custom_buf > pbas_type;) 3. on n'a pas les autres effets (non voulus) de l'héritage
C'est un détail, mais 3 a tout de même un effet concret dans notre cas : le stream comme le buf ont un membre getloc(), et on ne veut pas de celui du buf (qui renvoit probablement pas ce qu'on veut) un 'using stream_type::getloc;' fait l'affaire aussi, mais bon, avec la petite classe qui va bien on dit exactement ce qu'on fait, et c'est de plus en plus à la mode.
hmm, ah tiens d'ailleurs, en fait, il devrait être appelé member_from_base plutôt pour reflêter ce qu'il fait (transformer une base en membre), vous pensez pas ?
-- Sam
le Friday 12 September 2003 16:06, kanze@gabi-soft.fr écrivit :
class dbg_stream : public std::ostream, private virtual
std::custom_buf
{
dbg_stream() : std::ostream( this ) ...
} ;
boost/utility/base_from_member.hpp a été fait exprès pour ce cas :
class dbg_stream : private boost::base_from_member<custom_buf >,
public ::std::basic_ostream<CharType, CharTraits>
{ ...
c'est un détail, mais ça fait pile ce qu'on veut :
1. l'héritage privé assure la priorité du construction du buf.
2. le buf est accessible par this->pbase_type::member
(avec typedef boost::base_from_member<custom_buf > pbas_type;)
3. on n'a pas les autres effets (non voulus) de l'héritage
C'est un détail, mais 3 a tout de même un effet concret dans notre cas : le
stream comme le buf ont un membre getloc(), et on ne veut pas de celui du
buf (qui renvoit probablement pas ce qu'on veut)
un 'using stream_type::getloc;' fait l'affaire aussi, mais bon, avec la
petite classe qui va bien on dit exactement ce qu'on fait, et c'est de plus
en plus à la mode.
hmm, ah tiens d'ailleurs, en fait, il devrait être appelé member_from_base
plutôt pour reflêter ce qu'il fait (transformer une base en membre), vous
pensez pas ?
class dbg_stream : public std::ostream, private virtual std::custom_buf { dbg_stream() : std::ostream( this ) ... } ;
boost/utility/base_from_member.hpp a été fait exprès pour ce cas :
class dbg_stream : private boost::base_from_member<custom_buf >, public ::std::basic_ostream<CharType, CharTraits> { ...
c'est un détail, mais ça fait pile ce qu'on veut : 1. l'héritage privé assure la priorité du construction du buf. 2. le buf est accessible par this->pbase_type::member (avec typedef boost::base_from_member<custom_buf > pbas_type;) 3. on n'a pas les autres effets (non voulus) de l'héritage
C'est un détail, mais 3 a tout de même un effet concret dans notre cas : le stream comme le buf ont un membre getloc(), et on ne veut pas de celui du buf (qui renvoit probablement pas ce qu'on veut) un 'using stream_type::getloc;' fait l'affaire aussi, mais bon, avec la petite classe qui va bien on dit exactement ce qu'on fait, et c'est de plus en plus à la mode.
hmm, ah tiens d'ailleurs, en fait, il devrait être appelé member_from_base plutôt pour reflêter ce qu'il fait (transformer une base en membre), vous pensez pas ?
-- Sam
James Kanze
Samuel Krempp writes:
|> le Friday 12 September 2003 16:06, écrivit :
|> > class dbg_stream : public std::ostream, private virtual |> > std::custom_buf |> > { |> > dbg_stream() : std::ostream( this ) ... |> > } ;
|> boost/utility/base_from_member.hpp a été fait exprès pour ce cas :
|> class dbg_stream : private boost::base_from_member<custom_buf >, |> public ::std::basic_ostream<CharType, CharTraits> |> { ...
J'aurais dû penser qu'il y pourrait avoir quelque chose. L'inventateur de la technique, autant que je sache, c'est Dietmar Kühl, qui est aussi un des fondateurs de Boost.
|> c'est un détail, mais ça fait pile ce qu'on veut : |> 1. l'héritage privé assure la priorité du construction du buf. |> 2. le buf est accessible par this->pbase_type::member |> (avec typedef boost::base_from_member<custom_buf > pbas_type;) |> 3. on n'a pas les autres effets (non voulus) de l'héritage
|> C'est un détail, mais 3 a tout de même un effet concret dans |> notre cas : le stream comme le buf ont un membre getloc(), et on ne |> veut pas de celui du buf (qui renvoit probablement pas ce qu'on |> veut) un 'using stream_type::getloc;' fait l'affaire aussi, mais |> bon, avec la petite classe qui va bien on dit exactement ce qu'on |> fait, et c'est de plus en plus à la mode.
Je sais en effet que Dietmar avait trouvé une ou deux petites faiblesses avec la solution simple. Elles ne m'ont jamais causé de problème ; je m'y suis donc restée. Mais dans la mésure qu'on a la possibilité de faire mieux sans trop d'effort (puisque quelqu'un d'autre a déjà fait le travail), ça serait dommage de s'en passer.
|> hmm, ah tiens d'ailleurs, en fait, il devrait être appelé |> member_from_base plutôt pour reflêter ce qu'il fait |> (transformer une base en membre), vous pensez pas ?
En effet, ça me semble mieux.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Samuel Krempp <krempp@crans.truc.en.trop.ens-cachan.fr> writes:
|> le Friday 12 September 2003 16:06, kanze@gabi-soft.fr écrivit :
|> > class dbg_stream : public std::ostream, private virtual
|> > std::custom_buf
|> > {
|> > dbg_stream() : std::ostream( this ) ...
|> > } ;
|> boost/utility/base_from_member.hpp a été fait exprès pour ce cas :
|> class dbg_stream : private boost::base_from_member<custom_buf >,
|> public ::std::basic_ostream<CharType, CharTraits>
|> { ...
J'aurais dû penser qu'il y pourrait avoir quelque chose.
L'inventateur de la technique, autant que je sache, c'est Dietmar
Kühl, qui est aussi un des fondateurs de Boost.
|> c'est un détail, mais ça fait pile ce qu'on veut :
|> 1. l'héritage privé assure la priorité du construction du buf.
|> 2. le buf est accessible par this->pbase_type::member
|> (avec typedef boost::base_from_member<custom_buf > pbas_type;)
|> 3. on n'a pas les autres effets (non voulus) de l'héritage
|> C'est un détail, mais 3 a tout de même un effet concret dans
|> notre cas : le stream comme le buf ont un membre getloc(), et on ne
|> veut pas de celui du buf (qui renvoit probablement pas ce qu'on
|> veut) un 'using stream_type::getloc;' fait l'affaire aussi, mais
|> bon, avec la petite classe qui va bien on dit exactement ce qu'on
|> fait, et c'est de plus en plus à la mode.
Je sais en effet que Dietmar avait trouvé une ou deux petites
faiblesses avec la solution simple. Elles ne m'ont jamais causé de
problème ; je m'y suis donc restée. Mais dans la mésure qu'on a
la possibilité de faire mieux sans trop d'effort (puisque quelqu'un
d'autre a déjà fait le travail), ça serait dommage de s'en
passer.
|> hmm, ah tiens d'ailleurs, en fait, il devrait être appelé
|> member_from_base plutôt pour reflêter ce qu'il fait
|> (transformer une base en membre), vous pensez pas ?
En effet, ça me semble mieux.
--
James Kanze mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
|> > class dbg_stream : public std::ostream, private virtual |> > std::custom_buf |> > { |> > dbg_stream() : std::ostream( this ) ... |> > } ;
|> boost/utility/base_from_member.hpp a été fait exprès pour ce cas :
|> class dbg_stream : private boost::base_from_member<custom_buf >, |> public ::std::basic_ostream<CharType, CharTraits> |> { ...
J'aurais dû penser qu'il y pourrait avoir quelque chose. L'inventateur de la technique, autant que je sache, c'est Dietmar Kühl, qui est aussi un des fondateurs de Boost.
|> c'est un détail, mais ça fait pile ce qu'on veut : |> 1. l'héritage privé assure la priorité du construction du buf. |> 2. le buf est accessible par this->pbase_type::member |> (avec typedef boost::base_from_member<custom_buf > pbas_type;) |> 3. on n'a pas les autres effets (non voulus) de l'héritage
|> C'est un détail, mais 3 a tout de même un effet concret dans |> notre cas : le stream comme le buf ont un membre getloc(), et on ne |> veut pas de celui du buf (qui renvoit probablement pas ce qu'on |> veut) un 'using stream_type::getloc;' fait l'affaire aussi, mais |> bon, avec la petite classe qui va bien on dit exactement ce qu'on |> fait, et c'est de plus en plus à la mode.
Je sais en effet que Dietmar avait trouvé une ou deux petites faiblesses avec la solution simple. Elles ne m'ont jamais causé de problème ; je m'y suis donc restée. Mais dans la mésure qu'on a la possibilité de faire mieux sans trop d'effort (puisque quelqu'un d'autre a déjà fait le travail), ça serait dommage de s'en passer.
|> hmm, ah tiens d'ailleurs, en fait, il devrait être appelé |> member_from_base plutôt pour reflêter ce qu'il fait |> (transformer une base en membre), vous pensez pas ?
En effet, ça me semble mieux.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93