2008-10-23 11 views
2

Le code suivant compile correctement sous VC++ 8 sur XPSP3, mais son exécution provoque une erreur d'exécution.Manière correcte d'utiliser le foncteur personnalisé avec l'algorithme std :: generate_n()?

Mon tête ressemble à:

#include <stdexcept> 
#include <iterator> 
#include <list> 


template<typename T> 
class test_generator 
{ 
    public: 
    typedef T result_type; 

    //constructor 
    test_generator() 
    { 
     std::generate_n(std::back_inserter(tests), 100, rand); 
     value = tests.begin(); 
    } 

    result_type operator()(void) 
    { 
     if(value == tests.end()) 
     { 
      throw std::logic_error(""); 
     } 

      return *value++; 
    } 

    private: 

    std::list<T> tests; 
    typename std::list<T>::iterator value; 

}; 

Ma mise en œuvre ressemble:

#include <functional> 
#include <algorithm> 
#include <iostream> 
#include <deque> 

#include "test.h" 

int main() 
{ 
    test_generator<double> test; 
    std::deque<double> tests; 

    std::generate_n(std::back_inserter(tests), 10, test); 

    return 0; 
} 

Cette compile bien, il génère une exception (pas d'exception logic_error définie dans l'en-tête).

Si je change la mise en œuvre d'utiliser une fonction au lieu d'un foncteur, il fonctionne:

int main() 
{ 
    std::deque<int> tests; 
    std::generate_n(std::back_inserter(tests), 10, rand); 

    return 0; 
} 

Quel est le problème avec l'aide d'un foncteur ici?

Répondre

4

Le constructeur test_generatorvalue initialise l'itérateur pour référencer le premier élément de la liste tests (qui est un membre de test_generator).

Lorsque vous appelez std::generate_n, une copie du test est effectuée (car l'objet est transmis par valeur). Dans l'objet copié, l'itérateur value fait référence à la liste tests dans l'objet d'origine, pas la copie. En raison des vérifications de débogage de l'itérateur effectuées dans l'implémentation Visual Studio STL, cela déclenche une assertion, car un itérateur obtenu à partir d'un conteneur ne doit pas être comparé à un itérateur d'un autre conteneur.

Pour résoudre le problème, vous pouvez soit mettre en œuvre un constructeur de copie pour votre test_generator classe, ou reporter l'initialisation de value jusqu'à ce que la première fois operator() est invoquée.

+0

Déplacé l'initialisation de valeur dans la liste d'initialisation et implémenté un constructeur de copie, cela a résolu le problème. – paxos1977

0

Je n'ai pas encore trouvé ce qui cause l'exception jusqu'à présent, mais vous voudrez peut-être return *value++ dans votre operator(). :-)

+0

en changeant * (valeur ++) en * valeur ++ n'avait aucun effet. – paxos1977

+0

Je ne dis pas que * valeur ++ est différent de * (valeur ++), juste que votre exemple de code ci-dessus en a manqué. Mais il est bon que votre code actuel (que vous devriez coller, d'ailleurs) l'a. :-) –

+0

sry à propos de ça ... c'est en fait mon vrai code ... Je n'ai juste pas attrapé ça avant de poster. – paxos1977

Questions connexes