P2927 Proposal: Proposes a facility
exception_ptr_castwith signaturetemplate<class T> const T* exception_ptr_cast(const exception_ptr&) noexcept;.- Example usage in modifying Nicolas Guillemot's 2013 example:
FooResult lippincott(std::exception_ptr eptr) { assert(eptr!= nullptr); if (auto *ex = std::exception_ptr_cast<MyException1>(eptr)) { return FOO_ERROR1; } else if (auto *ex = std::exception_ptr_cast<MyException2>(eptr)) { return FOO_ERROR2; } else { if (auto *ex = std::exception_ptr_cast<std::exception>(eptr)) { log::warning("%s", ex->what()); } return FOO_UNKNOWN; } } try { foo::DoThing(); } catch (...) { return lippincott(std::current_exception()); } - Notes on the name
exception_ptr_castbeing redundant.
- Example usage in modifying Nicolas Guillemot's 2013 example:
- Danger of Calling with rvalue: It's dangerous to write
if (auto *ex = std::exception_ptr_cast<std::exception>(std::current_exception())) { std::cout << ex->what() << "\n"; }asstd::current_exceptionmay copy the in-flight exception to storage that lives only as long as theexception_ptr's reference count remains above zero. MSVC may do this and it will compile everywhere but cause a use-after-free on Windows. - Suggested Solution and Its Wrongness: Suggested to make it ill-formed to call
exception_ptr_castwith an rvalueexception_ptrby=deleteing the overload that preferentially binds to rvalues. But this is wrong as value category is not lifetime and we still want to be able to write code likeif (Result r = DoThing(); r.has_error()) if (auto *ex = std::exception_ptr_cast<std::exception>(r.error())) std::cout << ex->what() << "\n;even whenr.error()returns by value. - When is Deleting
const&&Overloads Desirable: Short answer is never desirable as value category is not lifetime. The eleven places where(const&&)=deleteappears in the STL today are in functions that return a pointer or reference to the argument itself. In theexception_ptr_castcase, it returns a pointer to the thing pointed to by the argument object and deleting the rvalue overload would break many things like in LLVM code. Examples includeCI.getPCHContainerOperations(),Context.takeReplaceableUses(),CreateInfoOutputFile, etc. Deleting rvalue overloads is a bad way to deal with dangling bugs and we must preserve the ability to pass and returnexception_ptrs by value.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。