在存在异常的情况下使用for_each? std::exception_list
Usage of for_each in the presence of exceptions? std::exception_list
cpppreferences documentation https://en.cppreference.com/w/cpp/algorithm/for_each 说:
- 如果作为算法的一部分调用的函数的执行引发异常,并且 ExecutionPolicy 是三个标准策略之一,则调用 std::terminate。对于任何其他执行策略,行为都是实现定义的。
我的解释是,这意味着我不能开箱即用地从for_each
传递的函数中抛出并期望捕获超出或与之相关的一些信息。
我期望使用异常的原因是我可以部分撤消(还原)for_each
调用中所做的更改。 (也许有更好的算法)。
然而,偶然地,我发现了for_each
的历史版本,该版本被记录为具有不同的、更有趣的行为:
http://man.hubwiz.com/docset/C.docset/Contents/Resources/Documents/output/en/cpp/algorithm/for_each.html
- 如果策略为 std::p arallel_vector_execution_policy,则调用 std::terminate
如果策略为 std::sequential_execution_policy 或 std:- :p arallel_execution_policy,则算法将以包含所有未捕获异常的 std::exception_list 退出。如果只有一个未捕获的异常,算法可能会在不包装 std::exception_list 的情况下重新引发它。未指定算法在遇到第一个异常后返回之前将执行多少工作。
这似乎意味着,而不是terminate
ing,而是有可能实际使用异常。
那么,为什么std::exception_list
被淘汰了?是不是太有争议,太复杂,太(内存)成本?
即使我同意这个逻辑,我真的没有任何其他选择,因为并行for_each
返回void
(而不是返回 UnaryFunction,这也令人惊讶)。 因此 在我看来,这个std::exception_list
协议是撤消失败完成for_each
指令的必要组件。
期望一些新的自定义策略是否合理,例如par_with_failed_list
将出现在允许undo
的某个地方。
更多上下文:这种撤消失败循环的模式用于容器的构造。我想实现一个自定义(并行/连续)uninitialized_value_construct_n
,当(任何未排序的)构造失败时,它会"撤消"(销毁)启动的对象。
EDIT1:不过,在一秒钟内,可以将lambda中捕获的变量传递给函数参数。 此变量可以是共享的并发数据,可以在异常发生时存储异常(作为exception_list)。 我想知道这是否已经完成。
编辑2:我在HPX中找到了exception_list
的实现,
https://github.com/STEllAR-GROUP/hpx/blob/master/hpx/exception_list.hpp
https://github.com/STEllAR-GROUP/hpx/blob/master/src/exception_list.cpp
std::exception_list
并行算法的规范和实现增加了很多复杂性,却没有太多相应的收益。
作为用户,您可以在函子中处理这种情况:
struct exception_info{
ElementType* element;
std::exception_ptr exception;
};
std::vector<exception_info> exceptions;
std::mutex exceptions_mutex;
std::vector<ElementType> range=...;
std::for_each(std::execution::par,range.begin(),range.end(),[&](ElementType& element){
try{ do_stuff(element); }
catch(...){
std::lock_guard guard(exceptions_mutex);
exceptions.push_back({&element,std::current_exception()});
}});
exceptions
列表现在将包含一个指向引发异常的元素和引发的异常的指针列表。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从持续时间构造std::chrono::system_clock::time_point
- std::具有相同基类的类的变体
- std::向量与传递值的动态数组
- 使用std::vector的OpenCL矩阵乘法
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- std::condition_variable::wait()如何评估给定的谓词
- 如何获取std::result_of函数的返回类型
- std::原子加载和存储都需要吗
- 将对象移动到std::shared_ptr
- POCO::PostgreSQL:如何将std::vector支持添加到`Binder::bind`
- 使用一个考虑到std::map中键值的滚动或换行的键
- 将函数应用于std::map值,其中包含for each和lambda函数
- g++ 4.4.7 -std=gnu++0x 应该编译"for each"结构吗?
- for-each 循环生成错误,但 for(it=begin()...在遍历 std::map 包含 unique_ptr 时不会
- 'for each'不是 std 的成员。 已启用 C++11 支持