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

C++ Discussion :

Problème de copie avec fstream


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Par défaut Problème de copie avec fstream
    Bonjour,

    J'ai une structure définie comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct X
    {
        std::ofstream file;
        // ...
    };
    et une classe Y qui stocke des X :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Y
    {
        private:
            std::unordered_map<std::string, X> data;
    };
    Mon soucis, c'est que lorsque je veux créer un nouveau X et le ranger dans data, le compilateur m'en empêche :

    error: use of deleted function 'X& X::operator=(const X&)'
    note: 'X& X::operator=(const X&)' is implicitly deleted because the default definition would be ill-formed:
    error: use of deleted function 'std::basic_ofstream<char>& std::basic_ofstream<char>::operator=(const std::basic_ofstream<char>&)'
    Comment puis-je m'en sortir ? J'aimerais pouvoir faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Y y;
    y.add_X ("ID", X(/* ... */));
    Comment puis-je le créer sans copie ? (j'utilise un mingw64 avec gcc 4.7).

  2. #2
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Il faudra utiliser un pointeur quelque part. Soit pour stocker le fstream dans X, soit pour stocker le X dans la map.

  3. #3
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Ton gcc gère la move semantic. Il est impossible de copier un fstream, mais il est possible de le déplacer.

    Déjà pour activer les nouveautés du C++11, il faut compiler avec le flag -std=c++11

    Ensuite, il faut que ton objet contenant un flux soit lui même déplaçable. Et finalement, pour mettre dans ta map, que tu ne génère pas de copie, mais un déplacement.

    Peut-être que si tu montre un peu plus de code il sera possible de voir où ça coince ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Par défaut
    Je compile déjà en C++11, pour pouvoir utiliser les unordered_map sans boost.

    Voici la classe X (partiellement) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct LogLevel
    {
    	LogLevel (const std::string & file_name, const std::string & msg_header = "[TRACE]", const std::string & date_format = "[%d/%m/%y - %H:%M]"):
    		file (file_name, std::ios::app), header (msg_header), file_name (file_name), date_format (date_format) {}
     
    	~LogLevel () { if (file.is_open()) file.close(); }
     
    	std::ofstream file;
    	std::string   header,
    	              file_name,
    	              date_format;
    };
    Et la classe Y (partiellement) :

    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
    class Logger
    {
    	public: // -- CONSTRUCTORS
    		Logger () = default;
    		Logger (std::initializer_list <LogLevel> levels);
     
    	public: // -- DATA MANAGEMENT
    		void register_level (const std::unordered_map<std::string, LogLevel> & levels)
    		{
    			for (auto it = levels.begin() ; it != levels.end() ; ++it)
    				this->levels[it->first] = LogLevel (it->second.file_name, it->second.header, it->second.date_format); // Problème ici
    		}
     
    	private: // -- DATA
    		std::unordered_map <std::string, LogLevel> levels;
    };
    J'aimerais pouvoir faire ça au final :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    logger.register_level (
    	{"UN_NIVEAU", LogLevel ("./logs/")},
    	{"UN_AUTRE", LogLevel ("./logs/other/")}
    );
    J'ai pensé utiliser un emplace, mais j'ai des tas d'autres erreurs.

  5. #5
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Je n'ai pas trop l'habitude de la move semantic, devant compiler sur des antiquités, mais je dirais à vue de nez :

    - Le destructeur dans LogLevel empêche la génération automatique d'un mode constructor de déplacement ou d'un opérateur= par déplacement. Donc soit tu supprimes ce destructeur (qui de toute façon n'a pas l'air utile, a moins que le vrai code fasse d'autres choses), soit tu déclares et défini ces deux opérations (éventuellement avec du =default, pour ne pas avoir à les implémenter). Ta classe est désormais movable

    - Comme dans ta ligne this->levels[it->first] = LogLevel (it->second.file_name, it->second.header, it->second.date_format);, ce que tu ajoutes dans ta map est un temporaire, le compilateur devrait choisir la version qui déplace, donc ton code devrait compiler.

    - Par contre, avec ce code, tu te retrouves à ouvrir deux fois le fichier de log simultanément, la seconde ouverture va probablement échouer, et donc le flux être dans un état d'erreur, et c'est celle là qui importe... Il serait donc probablement préférable de modifier ta fonction pour qu'elle prenne tes données par r-value ref aussi, prenant alors possession de celles ci, et t'obligeant lors de l'appel à lui passer des données temporaires qui ne seront plus utilisées après.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2011
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo

    Informations forums :
    Inscription : Août 2011
    Messages : 88
    Par défaut
    Je te remercie de tes réponses, cependant :

    - La mise en commentaire de mon constructeur ne change strictement rien. Par ailleurs, j'ai lu à plusieurs reprises que le destructeur d'un of/if/fstream ne fermait pas le fichier, et que donc il fallait le faire manuellement.
    J'ai donc ajouté les deux operations en mode = default; mais elles sont implicitement deleted par mon compilateur car il semblerait que mon ofstream n'ait pas de sémantique de déplacement.

    - A cette ligne précise, mon compilateur persiste à vouloir utiliser l'operator= (const ofstream &) plus que la version move, je suppose donc qu'elle n'existe pas.

    - De quelle façon puis-je arriver à ce résultat ? J'ai besoin de passer par le constructeur par initializer_list de mon unordered_map pour faire ce dont j'ai besoin, donc je ne peux pas me passer de celle-ci.

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

Discussions similaires

  1. [AC-2003] problème de copie avec UPDATE
    Par yieiyiei dans le forum VBA Access
    Réponses: 3
    Dernier message: 31/03/2015, 13h25
  2. Problème de copie d'une base de données MySQL avec PHP
    Par rheem dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 15/10/2007, 14h52
  3. problème de permissions avec fonction copy()
    Par jeanfrancois dans le forum Langage
    Réponses: 5
    Dernier message: 30/03/2006, 15h37
  4. Problème avec fstream
    Par cach dans le forum SL & STL
    Réponses: 17
    Dernier message: 27/02/2005, 12h28

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