2008-10-23 2 views
2

Следующий код компилируется правильно в VC++ 8 на XPSP3, но его запуск вызывает ошибку времени выполнения.Правильный способ использования пользовательского функтора с помощью std :: generate_n() алгоритма?

Мой заголовок выглядит следующим образом:

#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; 

}; 

Моя реализация выглядит следующим образом:

#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; 
} 

Это компилируется нормально, он генерирует исключение (а не исключение logic_error определено в заголовке).

Если изменить реализацию, чтобы использовать функцию вместо функтор, он работает:

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

    return 0; 
} 

Что случилось с использованием функтор здесь?

ответ

4

test_generator Конструктор инициализирует value итератора для ссылки на первый элемент в списке tests (который является членом test_generator).

Когда вы звоните std::generate_n, делается копия test (потому что объект передается по значению). В скопированном объекте итератор value ссылается на список tests в исходном объекте, а не на копию.

Из-за проверок отладки итератора, выполняемых в реализации STL Visual Studio, это вызывает утверждение, потому что итератор, полученный из одного контейнера, не следует сравнивать с итератором из другого контейнера.

Чтобы устранить эту проблему, можно либо реализовать конструктор копирования для test_generator класса, или отложить инициализацию value до первого operator() вызывается.

0

Я пока не понял, что вызывает исключение, но вы можете пожелать иметь return *value++ в своем operator(). :-)

+0

изменение * (значение ++) до * значение ++ не повлияло. – paxos1977 2008-10-23 20:09:39

+0

Я не говорю, что * значение ++ отличается от * (значение ++), просто что ваш пример кода выше не хватало. Но хорошо, что ваш фактический код (который вы должны вставить, кстати) имеет его. :-) – 2008-10-23 20:10:58

Смежные вопросы