【问题标题】:Correct way to use custom functor with std::generate_n() algorithm?将自定义函子与 std::generate_n() 算法一起使用的正确方法?
【发布时间】:2010-09-18 20:58:38
【问题描述】:

以下代码在 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;
}

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

【问题讨论】:

    标签: c++ stl functional-programming


    【解决方案1】:

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

    【讨论】:

    • 将 *(value++) 更改为 *value++ 没有任何影响。
    • 我并不是说 *value++ 与 *(value++) 不同,只是您上面的示例代码缺少它。但是,您的实际代码(顺便说一句,您应该粘贴)拥有它是很好的。 :-)
    • 对不起...这实际上是我的真实代码...我只是在发布之后才发现。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 将 value 的初始化移到初始化列表中,并实现了一个复制构造函数,这解决了这个问题。
    猜你喜欢
    • 1970-01-01
    • 2013-09-14
    • 2021-04-01
    • 1970-01-01
    • 2013-06-30
    • 2016-08-15
    • 2014-08-30
    • 2011-10-05
    • 2015-03-18
    相关资源
    最近更新 更多