使用std :: generate_n()算法的自定义函子的正确方法?

时间:2008-10-23 19:49:34

标签: c++ stl functional-programming

以下代码在XPSP3上的VC ++ 8下正确编译,但运行它会导致运行时错误。

我的标题如下:

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

在这里使用仿函数有什么问题?

2 个答案:

答案 0 :(得分:4)

test_generator构造函数初始化value迭代器以引用tests列表中的第一个元素(它是test_generator的成员)。

当您致电std::generate_n时,会生成test的副本(因为该对象是按值传递的)。在复制的对象中,value迭代器引用原始对象中的tests列表,而不是副本。

由于在Visual Studio STL实现中执行迭代器调试检查,因此会触发断言,因为从一个容器获取的迭代器不应与另一个容器的迭代器进行比较。

要解决此问题,您可以为test_generator类实施复制构造函数,也可以将value的初始化推迟到第一次调用operator()

答案 1 :(得分:0)

到目前为止,我还没有弄清楚导致异常的原因,但您可能希望return *value++中有operator()。 : - )