[PATCH] Implement std::visit<R> for C++2a (P0655R1)
Jonathan Wakely
jwakely@redhat.com
Mon Apr 8 16:23:00 GMT 2019
On 08/04/19 17:02 +0100, Jonathan Wakely wrote:
>+ template<typename _Result_type, typename _Visitor, typename... _Variants,
>+ size_t... __indices>
>+ struct __gen_vtable_r_impl<
>+ _Multi_array<_Result_type (*)(_Visitor, _Variants...)>,
>+ tuple<_Variants...>, std::index_sequence<__indices...>>
>+ {
>+ using _Array_type =
>+ _Multi_array<_Result_type (*)(_Visitor, _Variants...)>;
>+
>+ template<size_t __index, typename _Variant>
>+ static constexpr decltype(auto)
>+ __element_by_index_or_cookie(_Variant&& __var)
>+ {
>+ if constexpr (__index != variant_npos)
>+ return __variant::__get<__index>(std::forward<_Variant>(__var));
>+ else
>+ return __variant_cookie{};
>+ }
I don't think we need __element_by_index_or_cookie for the visit<R>
case, so the function above can go, and ...
>+ static constexpr _Result_type
>+ __visit_r_invoke(_Visitor&& __visitor, _Variants... __vars)
>+ {
>+ if constexpr (is_void_v<_Result_type>)
>+ return (void) std::__invoke(std::forward<_Visitor>(__visitor),
>+ __element_by_index_or_cookie<__indices>(
this just becomes __variant::__get<__indices>(
>+ std::forward<_Variants>(__vars))...);
>+ else
>+ return std::__invoke(std::forward<_Visitor>(__visitor),
>+ __element_by_index_or_cookie<__indices>(
and here too.
>+ std::forward<_Variants>(__vars))...);
>+ }
>+
>+ static constexpr _Array_type
>+ _S_apply()
>+ { return _Array_type{&__visit_r_invoke}; }
>+ };
With the above simplification the visit<R> code is a lot simpler than
the existing __gen_vtable code, let alone the version that adds
visit<R> support to it.
I'll spend some more time thinking about it.
>+ template<typename _Result_type, typename _Visitor, typename... _Variants>
>+ struct __gen_vtable_r
>+ {
>+ using _Array_type =
>+ _Multi_array<_Result_type (*)(_Visitor&&, _Variants...),
>+ variant_size_v<remove_reference_t<_Variants>>...>;
>+
>+ static constexpr _Array_type _S_vtable
>+ = __gen_vtable_r_impl<_Array_type, tuple<_Variants...>,
>+ std::index_sequence<>>::_S_apply();
N.B. here I just declare a variable and its default initializer. I
don't see any benefit to how the original in __gen_vtable does it:
static constexpr _Array_type
_S_apply()
{
return __gen_vtable_impl<_Array_type, tuple<_Variants...>,
std::index_sequence<>>::_S_apply();
}
static constexpr auto _S_vtable = _S_apply();
We only ever use that function in the default initializer, so might as
well get rid of it.
More information about the Libstdc++
mailing list