[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