IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

[C++11] stream et sémantique de déplacement


Sujet :

Langage C++

  1. #1
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut [C++11] stream et sémantique de déplacement
    Bonjour,

    ça faisait un certain temps que je n'avais pas posé une question ici, et cette nouvelle question est (comme la dernière il y a à peu près 1 an) lié à l'utilisation des rvalue reference. Un jour, je m'y ferait.

    Soit le code suivant, qui ne fait rien d'utile, mais qui est suffisament proche dans sa conception pour provoquer la même erreur que j'ai dans mon vrai code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    #include <sstream>
    #include <iostream>
     
    struct bbb
    {
    	int n;
    };
     
    struct aaa
    {
    	std::stringstream m_stream;
    	bbb& m_bobj;
     
    	aaa(bbb& bobj)
    	: m_bobj(bobj)
    	{ }
    	aaa(aaa&& other)
    	: m_stream(std::move(other.m_stream))
    	, m_bobj(other.m_bobj)
    	{ }
    	aaa& do_something()
    	{ m_stream << "show " << m_bobj.n; return *this ; }
    	void show()
    	{ std::cout << m_stream.str() << std::endl; }
    };
     
    aaa make(bbb& bobj)
    {
    	aaa aobj(bobj);
    	return aobj;
    }
     
    int main()
    {
    	bbb bobj = { 10 };
     
    	make(bobj).do_something().show();
    }
    L'idée derrière ce code est que je ne peux pas créer un objet aaa de manière explicite - il est prévu pour n'être jamais vu (ou en tout cas utilisé) par le programmeur. L'instance est créée par un appel à une fonction, et elle n'est jamais manipulée directement.

    Le problème est que ce type contient une référence ET un stream. Puisque l'instance est retournée par une fonction elle doit être soit copiable, soit moveable. Impossible qu'elle soit copiable (à cause de la référence ET du stream), j'opte donc pour un move ctor. Seulement, visiblement, j'ai des problèmes pour l'écrire...

    En compilant avec g++ (la version n'a pas d'importance ; le problème se produit aussi bien avec la version 4.5 que la version 4.7), j'obtiens les erreurs suivantes :

    show.cpp: In constructor ‘aaa::aaa(aaa&&)’:
    show.cpp:19:23: error: use of deleted function ‘std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)’
    In file included from show.cpp:1:0:
    /usr/include/c++/4.7/sstream:483:11: note: ‘std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
    /usr/include/c++/4.7/sstream:483:11: error: use of deleted function ‘std::basic_iostream<char>::basic_iostream(const std::basic_iostream<char>&)’
    In file included from /usr/include/c++/4.7/sstream:39:0,
    from show.cpp:1:
    /usr/include/c++/4.7/istream:789:11: note: ‘std::basic_iostream<char>::basic_iostream(const std::basic_iostream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
    /usr/include/c++/4.7/istream:789:11: error: use of deleted function ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’
    /usr/include/c++/4.7/istream:56:11: note: ‘std::basic_istream<char>::basic_istream(const std::basic_istream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
    /usr/include/c++/4.7/istream:56:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
    In file included from /usr/include/c++/4.7/ios:45:0,
    from /usr/include/c++/4.7/istream:40,
    from /usr/include/c++/4.7/sstream:39,
    from show.cpp:1:
    /usr/include/c++/4.7/bits/basic_ios.h:64:11: note: ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ is implicitly deleted because the default definition would be ill-formed:
    In file included from /usr/include/c++/4.7/ios:43:0,
    from /usr/include/c++/4.7/istream:40,
    from /usr/include/c++/4.7/sstream:39,
    from show.cpp:1:
    /usr/include/c++/4.7/bits/ios_base.h:788:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
    In file included from /usr/include/c++/4.7/ios:45:0,
    from /usr/include/c++/4.7/istream:40,
    from /usr/include/c++/4.7/sstream:39,
    from show.cpp:1:
    /usr/include/c++/4.7/bits/basic_ios.h:64:11: error: within this context
    In file included from /usr/include/c++/4.7/sstream:39:0,
    from show.cpp:1:
    /usr/include/c++/4.7/istream:56:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
    /usr/include/c++/4.7/istream:789:11: error: use of deleted function ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’
    In file included from /usr/include/c++/4.7/istream:41:0,
    from /usr/include/c++/4.7/sstream:39,
    from show.cpp:1:
    /usr/include/c++/4.7/ostream:56:11: note: ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
    /usr/include/c++/4.7/ostream:56:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
    /usr/include/c++/4.7/ostream:56:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
    In file included from /usr/include/c++/4.7/sstream:39:0,
    from show.cpp:1:
    /usr/include/c++/4.7/istream:789:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
    In file included from show.cpp:1:0:
    /usr/include/c++/4.7/sstream:483:11: error: use of deleted function ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’
    /usr/include/c++/4.7/sstream:483:11: error: use of deleted function ‘std::basic_stringbuf<char>::basic_stringbuf(const std::basic_stringbuf<char>&)’
    /usr/include/c++/4.7/sstream:60:11: note: ‘std::basic_stringbuf<char>::basic_stringbuf(const std::basic_stringbuf<char>&)’ is implicitly deleted because the default definition would be ill-formed:
    In file included from /usr/include/c++/4.7/ios:44:0,
    from /usr/include/c++/4.7/istream:40,
    from /usr/include/c++/4.7/sstream:39,
    from show.cpp:1:
    /usr/include/c++/4.7/streambuf:800:7: error: ‘std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const __streambuf_type&) [with _CharT = char; _Traits = std::char_traits<char>; std::basic_streambuf<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>]’ is private
    In file included from show.cpp:1:0:
    /usr/include/c++/4.7/sstream:60:11: error: within this context
    Qu'est ce que je fais de mal ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  2. #2
    Membre éprouvé

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Points : 1 086
    Points
    1 086
    Par défaut
    Le problème est peut-être que m_stream fait trop de choses à la fois... est-ce que le scinder en un conteneur de données (std::string facilement déplaçable) et un flux "sans-état" (std::stringstream recréé de zéro) ne faciliterait pas les choses ?

  3. #3
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Si je ne me goure pas, les messages d'erreurs t'indiquent que std::stringstream fourni par gcc n'a pas encore de constructeur par deplacement. (Ce qui semble confirme en regardant le contenu de sstream ici).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  4. #4
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Malheureusement je crains fort que ce ne soit une nouvelle répercussion de ce problème :
    http://www.developpez.net/forums/d12...m/#post6663928

    C'est un peu toujours la même la malédiction concernant GCC. Ils ont été très largement en avance sur toute la concurrence pour implémenter le C++11 et c'est encore maintenant probablement le compilateur le plus compliant au niveau du core language, en revanche il y a parfois quelques trous dans la biblio standard qui prennent largement par surprise : Faut voir le nombre de gens qui ont posté sur stack overflow suite à des résultats faux voire des plantages bizarres en voulant utiliser <regex>, car la bonne blague c'est que <regex> est partiellement implémentée sur libstdc++ Personnellement je suis tombé sur un cas qui m'a aussi beaucoup surpris et c'est l'absence de std::wstring_convert. Ou encore l'absence des fonctions emplace pour std::map.

  5. #5
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par cob59 Voir le message
    Le problème est peut-être que m_stream fait trop de choses à la fois... est-ce que le scinder en un conteneur de données (std::string facilement déplaçable) et un flux "sans-état" (std::stringstream recréé de zéro) ne faciliterait pas les choses ?
    Ca pourrait presque être une solution, mais en fait, dans mon cas réel, aaa se comporte "comme un stream". Je voulais garder un stringstream sous jacent pour simplifier le développement - parce que garder la trace des manipulateurs, c'est un peu ardu

    Je vous modifie le code pour montrer ce point précis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #include <sstream>
    #include <iostream>
     
    struct bbb
    {
    	int n;
    };
     
    struct aaa
    {
    	std::stringstream m_stream;
    	bbb& m_bobj;
     
    	aaa(bbb& bobj)
    	: m_bobj(bobj)
    	{ }
    	aaa(aaa&& other)
    	: m_stream(std::move(other.m_stream))
    	, m_bobj(other.m_bobj)
    	{ }
    	aaa& do_something()
    	{ m_stream << "show " << m_bobj.n; return *this ; }
    	void show()
    	{ std::cout << m_stream.str() << std::endl; }
     
    	template <class Arg>
    	aaa& operator<<(Arg arg)
    	{ m_stream << arg; return *this; }
    };
     
    aaa make(bbb& bobj)
    {
    	aaa aobj(bobj);
    	return aobj;
    }
     
    int main()
    {
    	bbb bobj = { 10 };
     
    	make(bobj).do_something().show();
    	make(bobj) << "test" << " me";
    }
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Je confirme les propos de Arzar, pas de move constructeur dans mes headers de stringstream (gcc 4.8)
    Reste plus qu'a utiliser la bonne vieille sémantique d'entité avec pointeur...

    EDIT : bug connu et signalé : http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
    Pas de date prévu pour la correction (problème avec l'ABI)

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Merci gbdivers et Azrar. J'ai eu le même écho de la part de Winjerome.

    J'aime bien le commentaire sur le bugzilla de GNU :

    the implementation is being delayed to when we globally break the ABI.
    Plus précis que ça, tu meurs... (ceci dit, j'ai du mal à voir comment une modification de la librairie va casser l'ABI).

    Bon, je vais passer par un pointeur. C'est sale à souhait, mais bon, que faire d'autre ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    que faire d'autre ?
    Faire un patch pour gcc ?

  9. #9
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par gbdivers Voir le message
    Faire un patch pour gcc ?
    Non, inutile. Je suppose que le fix existe déjà, mais que ce fix nécessite des changements dans l'ABI - et donc ne sera pas pushé avant gcc 5.0.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. DirectSound et le streaming
    Par Shakram dans le forum DirectX
    Réponses: 57
    Dernier message: 09/06/2005, 11h05
  2. Streaming fichier PDF
    Par rgarnier dans le forum XMLRAD
    Réponses: 4
    Dernier message: 22/05/2003, 22h14
  3. Comment enregistrer un stream de longueur fixe ?
    Par Alcarbone dans le forum MFC
    Réponses: 5
    Dernier message: 13/04/2003, 20h14
  4. Déplacement "automatique" du curseur
    Par Amenofis dans le forum Composants VCL
    Réponses: 2
    Dernier message: 08/01/2003, 18h57
  5. Limiter le déplacement de la souris
    Par el_bouleto dans le forum C++Builder
    Réponses: 4
    Dernier message: 08/11/2002, 23h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo