P2927 Proposal: Proposes a facility
exception_ptr_cast
with 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_cast
being 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_exception
may 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_cast
with an rvalueexception_ptr
by=delete
ing 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&&)=delete
appears in the STL today are in functions that return a pointer or reference to the argument itself. In theexception_ptr_cast
case, 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_ptr
s by value.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。