[libcxx-commits] [libcxx] [libcxx] Enrich message for std::bad_variant_access exception (PR #196495)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jun 17 09:28:59 PDT 2026
================
@@ -309,11 +322,11 @@ struct __farray {
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __n) const noexcept { return __buf_[__n]; }
};
-[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_variant_access() {
+[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_variant_access(const char* __msg) {
# if _LIBCPP_HAS_EXCEPTIONS
- throw bad_variant_access();
+ throw __bad_variant_access_with_msg(__msg);
----------------
ldionne wrote:
Are we allowed to actually throw something that is not *exactly* `bad_variant_access`? Doesn't that break code like this?
```c++
#include <variant>
#include <cassert>
#include <typeinfo>
int main() {
std::variant<int, float> v(1);
try {
(void)std::get<float>(v);
} catch (std::bad_variant_access const& exc) {
assert(typeid(exc) == typeid(std::bad_variant_access));
}
}
```
I tried adding that test in the suite and it does fail. The only question is whether users are allowed to rely on it, but I think they are. In practice, I'd expect this shows up way more subtly than `assert(typeid(...) == typeid(...))`, but you get the point. `get` clearly says: https://eel.is/c++draft/variant#get-7
> Effects: If v.index() is I, returns a reference to the object stored in the variant[.](https://eel.is/c++draft/variant#get-7.sentence-1) Otherwise, throws an exception of type bad_variant_access[.](https://eel.is/c++draft/variant#get-7.sentence-2)
So, sadly, I don't think this derived class trick is legal. @philnik777 WDYT?
https://github.com/llvm/llvm-project/pull/196495
More information about the libcxx-commits
mailing list