Tested on Linux-PPC64. I haven't tested this with clang yet, Jonathan, can you help with that? The previous implementation indeed made an if-constexpr branch invalid for all instantiations of that branch, this one doesn't - now we have just a dependent static_assert which is well-formed for correct visitors and ill-formed for incorrect visitors.
2020-10-16 Ville Voutilainen <ville.voutilai...@gmail.com> PR libstdc++/97449 * include/std/variant (__gen_vtable_impl<>::_S_apply_single_alt): Diagnose visitor return type mismatches here.. (__gen_vtable_impl</*base case*/>::_S_apply): ..not here.
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index a29c5bf513b..17f8bcd638b 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -960,9 +960,13 @@ namespace __variant } else { - __element = __gen_vtable_impl< + auto __tmp_element = __gen_vtable_impl< remove_reference_t<decltype(__element)>, std::index_sequence<__indices..., __index>>::_S_apply(); + static_assert(is_same_v<_Tp, decltype(__tmp_element)>, + "std::visit requires the visitor to have the same " + "return type for all alternatives of a variant"); + __element = __tmp_element; } } }; @@ -1026,10 +1030,8 @@ namespace __variant std::declval<_Variants>()...))>; if constexpr (__visit_ret_type_mismatch) { - static_assert(!__visit_ret_type_mismatch, - "std::visit requires the visitor to have the same " - "return type for all alternatives of a variant"); - return __nonesuch{}; + struct __cannot_match {}; + return __cannot_match{}; } else return _Array_type{&__visit_invoke};