我想知道为什么std::current_exception()
在这种情况下的工作方式不同:
std::exception_ptr e, e2;
try {
std::string("abcd").substr(42);
} catch(std::exception &ex) {
std::cerr << "(1) Exception: " << ex.what() << std::endl;
e = std::current_exception();
e2 = std::make_exception_ptr(ex);
}
handle_exception(e);
handle_exception(e2);
而handle_exception打印异常:
void handle_exception(std::exception_ptr e)
{
try {
if (e)
std::rethrow_exception(e);
} catch(const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
}
输出如下:
(1) Exception: basic_string::substr: __pos (which is 42) > this->size() (which is 4)
(2) Exception: basic_string::substr: __pos (which is 42) > this->size() (which is 4)
(3) Exception: std::exception
但是我希望得到以下结果:
(1) Exception: basic_string::substr: __pos (which is 42) > this->size() (which is 4)
(2) Exception: basic_string::substr: __pos (which is 42) > this->size() (which is 4)
(3) Exception: basic_string::substr: __pos (which is 42) > this->size() (which is 4)
我在这里缺少什么?
答案 0 :(得分:3)
std::make_exception_ptr()
按值计算其参数。这意味着复制或就地构造。
你正在复制std :: exception(即切片)
答案 1 :(得分:1)
throw
请务必注意,C ++ throw
(我将仅讨论其与操作数的用法,例如throw someExpression;
)。对所传递的操作数的类型很敏感。它复制其操作数(从中复制初始化一个辅助对象)。复制是根据操作数的(词法)类型完成的(不是通过动态获取类)。
例如:
try {
std::runtime_error myException("Some test message");
std::exception &upcastedMyException = myException;
throw upcastedMyException; //std::exception is thrown
} catch(const std::exception &caught) {
std::cout << caught.what() << std::endl; //will output "std::exception"
}
它与其他语言不同,例如Java:
try {
RuntimeException myException = new RuntimeException();
Exception upcastedMyException = myException;
throw upcastedMyException; //RuntimeException is thrown
} catch(Exception caught) {
System.out.println(caught.getClass()); //will output "java.lang.RuntimeException"
}
因此,传递给C ++ throw
的表达式具有正确的类型非常重要。在我的第一个示例中,将throw upcastedMyException
替换为throw static_cast<const std::runtime_error &>(upcastedMyException)
(例如)将更改输出。
std::make_exception_ptr
std::make_exception_ptr
是通过throw
以非常简单的方式实现的:
template<class E> std::exception_ptr make_exception_ptr(E e) noexcept {
try {
throw e; //note this line
} catch(...) {
return std::current_exception();
}
}
这意味着std::make_exception_ptr
对传递的模板参数敏感;如果未显式传递模板参数,则std::make_exception_ptr
对所传递的函数参数的(词法)类型敏感(这会影响模板参数的推导):
std::make_exception_ptr(ex)
(其中ex
被声明为const std::exception &
),则std::exception
将被抛出到std::make_exception_ptr
和{{1 }}将返回与std::make_exception_ptr
相关的std::exception_ptr
。std::exception
,则std::make_exception_ptr(static_cast<const std::logic_error &>(ex))
将被抛出到std::logic_error
中,而std::make_exception_ptr
将返回与std::make_exception_ptr
相关的std::exception_ptr
。std::logic_error
,则std::make_exception_ptr(static_cast<const std::out_of_range &>(ex))
将被抛出到std::out_of_range
中,而std::make_exception_ptr
将返回与std::make_exception_ptr
相关的std::exception_ptr
。