iterator_traits <initer> :: value_type的创建是否会在传递时触发deference? (异常测试)</initer>

时间:2014-06-17 20:28:21

标签: c++ exception c++11 boost iterator

我故意为那些没有特别依赖迭代的函数抛出异常(用于测试目的)。要了解我在做什么,请使用我的decorator_iterator结构:

struct decorated_iterator
      : boost::iterator_adaptor<
            decorated_iterator<BaseIterator, IteratorTag>,
            BaseIterator, boost::use_default, IteratorTag>
    {
        //....
    private:
        friend class boost::iterator_core_access;

        /* used to throw an exception upon dereference */
        typename base_type::reference dereference() const
        {
            m_callback();
            return *(this->base());
        }

    private:
        std::function<void()> m_callback;
    };

decorator_iterator允许我将回调附加到在取消引用时触发的迭代器,使用此我可以使用

测试异常抛出
try {

    copy(
        decorated_iteartor(iter, [](){throw std::runtime_error("test");}),
        decorated_iterator(iter, [](){}),
        begin(destiter));
}
//catch runtime!

这个函数非常适合我的一些特定取消引用指针的实现,例如

[](reference it) {
    //triggers callback
    *it = ...
}

我现在的问题是当我正在进行std::count的并行实现时,我的所有异常测试都失败了。我的猜测是我从未在lambda函数中专门取消引用迭代器,而是使用iterator_traits<InIter>::value_type。如果值类型不能取消引用,我可以在decorator_iterator或我的函数中修改什么来导致回调被执行?特定的计数超载给我带来了麻烦:

template <typename ExPolicy, typename InIter, typename T>
typename detail::algorithm_result<ExPolicy, 
    typename std::iterator_traits<InIter>::difference_type>::type
count(ExPolicy const& policy, InIter first, InIter last, const T& value,
boost::mpl::false_ f)
{
    //get a value_type to compare to passed value
    typedef typename std::iterator_traits<InIter>::value_type type;
    typename std::iterator_traits<InIter>::difference_type ret = 0;

    //from first to last, execute the following lambda
    for_each_n(policy,
        first, std::distance(first,last),
        [&value, &ret](type v) {
            if (v == value)
                ret++;
        }, f);

    return detail::algorithm_result<ExPolicy, 
        typename std::iterator_traits<InIter>::difference_type>::get(std::move(ret));

}

注意:我尝试过简单地修改lambda以传递InIter ref并使用*ref,但这样做无效并且会给我错误。

1 个答案:

答案 0 :(得分:0)

迭代器只提供明确定义的操作集。

除了使用标准定义的解除引用操作(间接运算符或*it)之外,我不知道任何其他(明确定义的)解除引用迭代器的方法。

您可以看到针对例如优化的实施方案std :: vector :: iterator,(例如,如果元素类型是POD,则使用memcpy / memmov)。但是我认为对于一个库(在这种情况下是你的并行算法库)来说,对于用户提供的迭代器做出这样的假设是一个坏主意。换句话说,如果库检测到基本迭代器类型并以绕过用户定义迭代器的副作用的方式对其进行优化,则将是严重的我认为错误

开箱即用,解释可能是异常不会(立即)从工作线程传播。我不知道ExPolicy是什么,但它可能是例外政策。

我完全可以想象该算法返回future<size_t>(可能取决于ExPolicy参数),因此在.get()之前您不会看到异常未来的价值?