[v3 PATCH, RFC] Rewrite variant. Also PR libstdc++/85517
Ville Voutilainen
ville.voutilainen@gmail.com
Tue Feb 5 22:05:00 GMT 2019
Okay then. This patch takes the hopefully biggest steps towards
a std::variant rewrite. The problem we have with the current
approach is that we'd really like to write fairly straightforward
code for variant's special member functions, but can't, because
the specification suggests fairly straightforward compile-time-property
queries and selection of behavior based on those, but variant's selected
index is a run-time property. This leads to difficulties implementing
what the standard requires, like the differences of handling throwing and
non-throwing move/copy operations of the types held in variant.
Well. We apply the hammer of Pattern Matching. variant's visit()
can get us into code that can do the compile-time queries despite
variant's selected index being a run-time property. We modify
the visitation mechanism to not throw an exception if invoked
with a special kind of visitor that can handle valueless variants,
and then use polylambdas as such visitors, and do if-constexprs
in those polylambdas.
We can now get rid of the function-pointer tables that are used for
similar kind of dispatching in the original approach. Visitation
generates similar tables, so we keep the O(1) indexing into the right
function based on the current selected index, and there's the same
amount of indirect calls through a pointer-to-function, one.
Our code for e.g. variant's copy assignment is now straightforward;
it visits both the this-variant and the rhs-variant at the same time,
and does the right thing based on the compile-time properties of the
selected type,
and whether either variant is valueless. Modulo the polylambda wrapping
and the fact that all ifs in it are if-constexprs, it looks like it's just
doing conditional code based on what the nothrow-properties, for example,
of the type of the object held by the variant are.
This patch also partially gets rid of some of the cases where an object
is self-destroyed before it's reconstructed. We shouldn't do that.
We should be doing _M_reset followed by _M_construct, so that we only
ever destroy a variant member of a union object held in the variant's
storage, and then try to reconstruct that (or some other variant member),
and we should never self-destroy any object in the inheritance chain of
variant. The rest of that is work-in-progress, as is changing the rest
of the special member functions to use visitation.
Thoughts?
2019-02-05 Ville Voutilainen <ville.voutilainen@gmail.com>
Rewrite variant.
Also PR libstdc++/85517
* include/std/variant (__do_visit): New.
(__variant_cast): Likewise.
(__variant_cookie): Likewise.
(__erased_dtor): Remove.
(_Variant_storage::_S_vtable): Likewise.
(_Variant_storage::__M_reset_impl): Adjust to use __do_visit.
(_Variant_storage::__M_reset): Adjust.
(_Move_ctor_base::__M_destructive_copy): New.
(_Copy_assign_base::operator=): Adjust to use __do_visit.
(_Copy_assign_alias): Adjust to check both copy assignment
and copy construction for triviality.
(_Multi_array): Add support for visitors that accept and return
a __variant_cookie.
(__gen_vtable_impl::_S_apply_all_alts): Likewise.
(__gen_vtable_impl::_S_apply_single_alt): Likewise.
(__gen_vtable_impl::__element_by_index_or_cookie): New. Generate
a __variant_cookie temporary for a variant that is valueless and..
(__gen_vtable_impl::__visit_invoke): ..adjust here.
(__gen_vtable::_Array_type): Conditionally make space for
the __variant_cookie visitor case.
(variant): Add __variant_cast as a friend.
(variant::emplace): Use _M_reset() instead of self-destruction.
(visit): Reimplement in terms of __do_visit.
* testsuite/20_util/variant/compile.cc: Adjust.
* testsuite/20_util/variant/run.cc: Likewise.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: variant-redesign-1.diff
Type: text/x-patch
Size: 15479 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20190205/84839095/attachment.bin>
More information about the Libstdc++
mailing list