C++11 如何扩展类模板,如 std::p ackaged_task
C++11 how to extend a class template such as std::packaged_task
我正在尝试扩展std::packaged_task
来处理SEH异常,但我无法编译它。
以下内容不编译:
#include <stdio.h>
#include <functional>
#include <future>
#include <windows.h>
template<class RET, class... ARGS>
class SafePackagedTask : public std::packaged_task<RET(ARGS...)>
{
public:
template<class F>
explicit SafePackagedTask(F && f)
: std::packaged_task*(std::forward<F>(f))
{
}
void operator()(ARGS... args)
{
__try
{
std::packaged_task*(std::forward<ARGS>(args));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("SEH Exception 0x%08lX in SafePackagedTask!n", GetExceptionCode());
}
}
};
int main()
{
SafePackagedTask<int()> task([] {
//int *a = nullptr; *a = 1; // generate SEH
return 1;
});
std::future<int> fut = task.get_future();
task();
int rc = fut.get();
printf("result: %dn", rc);
}
错误是:
source_file.cpp(9): error C2091: function returns function
source_file.cpp(37): note: see reference to class template instantiation 'SafePackagedTask<int (void)>' being compiled
source_file.cpp(38): error C2440: 'initializing': cannot convert from 'std::future<_Ret>' to 'std::future<int>'
with
[
_Ret=int (__cdecl *)(void)
]
source_file.cpp(38): note: No constructor could take the source type, or constructor overload resolution was ambiguous
在 rextester.com 上看到它。
您正在尝试解决一个已经解决的问题。
通过在VC++上设置特定标志(您显然正在使用该标志),可以像常规C++标准异常一样处理SEH异常*
代码生成 ->在"是,有 SEH 例外"上设置"启用C++例外"。
现在您可以使用catch(...)
子句捕获 SEH 异常:
try{
}catch(std::exception& e){}
catch(...) {/*your code here*}
除此之外,处理 SEH 异常的最佳方法不是首先创建它们。 不尝试读取数组边界之外的内容,检查空指针,在需要时使用智能指针,并仔细编写类以使用 RAII,可能会消除代码中 95% 的异常。
*基本上,在Windows上,所有C++异常都是Windows SEH的子集,并以此方式实现。
许多 std 类不打算继承自。一个线索是,如果析构函数不是虚拟的,那么,至少,该类不打算多态使用。
终于让它工作了。
#include <stdio.h>
#include <functional>
#include <future>
#include <windows.h>
template<class RET, class... ARGS>
class SafePackagedTask;
template<class RET, class... ARGS>
class SafePackagedTask<RET(ARGS...)> : public std::packaged_task<RET(ARGS...)>
{
public:
template<class F>
explicit SafePackagedTask(F && f)
: std::packaged_task<RET(ARGS...)>(std::forward<F>(f))
{
}
void operator()(ARGS... args)
{
__try
{
std::packaged_task<RET(ARGS...)>::operator()(std::forward<ARGS>(args)...);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("SEH Exception 0x%08lX in SafePackagedTask!n", GetExceptionCode());
// ... print stack trace ...
}
}
};
int main()
{
SafePackagedTask<int()> task([] {
int *a = nullptr; *a = 1; // generate SEH
return 1;
});
std::future<int> fut = task.get_future();
try
{
task();
int rc = fut.get();
printf("result: %dn", rc);
}
catch (std::exception& e)
{
printf("error inside lambda: %sn", e.what());
}
return 0;
}
不幸的是,它/EHa
模式下没有做我想做的事,因为packaged_task
有一个catch(...)
可以捕获所有内容,然后重新投掷future::get()
。永远不会到达__except
处理程序,并且原始堆栈跟踪将丢失。所以我放弃了这种方法,并包装了底层任务本身:
template <typename F>
struct SafeTaskWrapper : F
{
SafeTaskWrapper(F&& f) : F(std::move(f)) {}
SafeTaskWrapper(SafeTaskWrapper&&) = default;
SafeTaskWrapper& operator=(SafeTaskWrapper&&) = default;
SafeTaskWrapper(const SafeTaskWrapper&) = default;
SafeTaskWrapper& operator=(const SafeTaskWrapper&) = default;
void operator()()
{
__try
{
F::operator()();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("SEH Exception 0x%08lX in lambda!n", GetExceptionCode());
// ... print stack trace ...
throw std::runtime_error("SEH Exception in lambda");
}
}
};
template <typename T>
auto make_safe_task(T&& t) -> SafeTaskWrapper<typename std::decay<T>::type>
{
return std::move(t);
}
int main()
{
std::packaged_task<int()> task(make_safe_task([] {
//int *a = nullptr; *a = 1; // generate SEH
return 1;
}));
std::future<int> fut = task.get_future();
try
{
task();
int rc = fut.get();
printf("result: %dn", rc);
}
catch (std::exception& e)
{
printf("error inside lambda: %sn", e.what());
}
return 0;
}
相关文章:
- 使用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::atomic 中提取指针 T<T>?
- 为什么 std::unique 不调用 std::sort?
- 使用std::函数映射对象方法
- 可组合的lambda/std::函数与std::可选