Re: [boost] [review][variant2] Variant2 Review Starts April 1
The class boost::variant2::variant
is an almost conforming implementation of std::variant with the following differences:
I see the useful comparison to std::variant in the doc, however I'm using boost::variant extensively in my code. It would be very useful to have also a short comparison to boost::variant in the doc, as I would expect many more current users of the venerable boost::variant than of its much younger cousin std::variant. Thanks!
dariomt--- wrote:
The class boost::variant2::variant
is an almost conforming implementation of std::variant with the following differences: I see the useful comparison to std::variant in the doc, however I'm using boost::variant extensively in my code.
It would be very useful to have also a short comparison to boost::variant in the doc, as I would expect many more current users of the venerable boost::variant than of its much younger cousin std::variant.
The main difference is that Variant2 is a pin-compatible replacement for std::variant, whereas Boost.Variant isn't (at least for now). So it's easier to switch from std::variant to Variant2 and back (depending f.ex. on whether std::variant is available.) The second most important difference would probably be the fact that Boost.Variant may do heap allocations.
On Mon, 25 Mar 2019 at 17:18, dariomt--- via Boost
... as I would expect many more current users of the venerable boost::variant than of its much younger cousin std::variant.
Why do you expect that and do you think that will stay that way? My personal feeling is that C++17-use is picking up at break-neck speed. For good or for worse, although there appears to be a lot of controversy over a (any) variant [and there are quite some quite different implementations around], the std::variant is the one in the std, which seems to give it a head start. In my view there can only be one objective with boost varant2, and that is if it is decided [here] that it is (much) better than the current std::variant, the C++20 std::variant should be/become the proposed boost::variant2. degski -- *Microsoft, please kill Paint3D*
On Mon, Mar 25, 2019, 12:33 PM degski via Boost
In my view there can only be one objective with boost varant2, and that is if it is decided [here] that it is (much) better than the current std::variant, the C++20 std::variant should be/become the proposed boost::variant2.
I don't think that's realistic based both on how the committee operates and specifically on what happened with std::variant standardization. The high-level design approach that variant2 takes was discussed during standardization, but it differed from the proposal that was moving forward and did not get consensus. Even if the standards committee were to now decide that std::variant *should* be changed, it would be a breaking change of a kind that the committee has historically had a hard time doing, even when it comes to fixing design bugs. I just don't see std::variant changing here. Separately, I don't think it is a problem that there are multiple variant-like type implementations. Over the past couple of years, people seem to have become a little bit too enamored with the notion of a "vocabulary" type and take it further than is healthy. std::variant can still be the "vocabulary" type in its current form and that's okay. We have multiple sum types in boost and in the standard and in proposals (optional, variant, expected). That's fine just as it is fine (and healthy) that we have multiple containers. std::variant can still be a "vocabulary" type just in the sense that std::vector is a vocabulary type. With std::variant standardization the discussions often centered around two competing and valid views with different trade-offs. One view was that a variant should never be empty (like boost::variant). The other view was that it is okay for there to be an empty state and that it can lead to a simpler and more efficient implementation (which can be true, but leads to a type with more states/weaker invariants). In the standard we ended up with a compromise that had an empty state that we *sometimes* try to avoid, but that actually can have negative performance and binary size implications for some operations, but some operations like assignments can potentially be faster and the type can be smaller. That's just what the committee ended up with in the presence of people shouting from different sides, along with a fair share of misunderstandings of the basic exception guarantee. As long as the committee wants exactly one type, I suspect it won't be able to do anything drastically different in either direction. Peter's variant can live here as the fully realized never-empty variant, and there can hypothetically be the opposing realization (i.e. something that goes to the other extreme and doesn't do anything to avoid the empty state ever, but has operations with strong preconditions -- I've even started implemented one even though I'm more fond of never-empty variants https://github.com/mattcalabrese/argot/blob/master/include/argot/discriminat... ). As long as there are non-trivial trade-offs for any type/template, there will be reasonable users who would opt for different trade-offs when in different domains. We just have to decide which combinations of the trade-offs are worth collecting into a facility that is present in boost or the standard or elsewhere.
wt., 26 mar 2019 o 17:46 Matt Calabrese via Boost
On Mon, Mar 25, 2019, 12:33 PM degski via Boost
wrote: In my view there can only be one objective with boost varant2, and that is if it is decided [here] that it is (much) better than the current std::variant, the C++20 std::variant should be/become the proposed boost::variant2.
I don't think that's realistic based both on how the committee operates and specifically on what happened with std::variant standardization. The high-level design approach that variant2 takes was discussed during standardization, but it differed from the proposal that was moving forward and did not get consensus. Even if the standards committee were to now decide that std::variant *should* be changed, it would be a breaking change of a kind that the committee has historically had a hard time doing, even when it comes to fixing design bugs. I just don't see std::variant changing here.
Separately, I don't think it is a problem that there are multiple variant-like type implementations. Over the past couple of years, people seem to have become a little bit too enamored with the notion of a "vocabulary" type and take it further than is healthy. std::variant can still be the "vocabulary" type in its current form and that's okay. We have multiple sum types in boost and in the standard and in proposals (optional, variant, expected). That's fine just as it is fine (and healthy) that we have multiple containers. std::variant can still be a "vocabulary" type just in the sense that std::vector is a vocabulary type.
With std::variant standardization the discussions often centered around two competing and valid views with different trade-offs. One view was that a variant should never be empty (like boost::variant). The other view was that it is okay for there to be an empty state and that it can lead to a simpler and more efficient implementation (which can be true, but leads to a type with more states/weaker invariants). In the standard we ended up with a compromise that had an empty state that we *sometimes* try to avoid, but that actually can have negative performance and binary size implications for some operations, but some operations like assignments can potentially be faster and the type can be smaller. That's just what the committee ended up with in the presence of people shouting from different sides, along with a fair share of misunderstandings of the basic exception guarantee. As long as the committee wants exactly one type, I suspect it won't be able to do anything drastically different in either direction. Peter's variant can live here as the fully realized never-empty variant, and there can hypothetically be the opposing realization (i.e. something that goes to the other extreme and doesn't do anything to avoid the empty state ever, but has operations with strong preconditions -- I've even started implemented one even though I'm more fond of never-empty variants
https://github.com/mattcalabrese/argot/blob/master/include/argot/discriminat... ).
As long as there are non-trivial trade-offs for any type/template, there will be reasonable users who would opt for different trade-offs when in different domains. We just have to decide which combinations of the trade-offs are worth collecting into a facility that is present in boost or the standard or elsewhere.
True. And maybe names of different variants of variant should reflect the different trade-offs. Maybe noempty::variant rather than variant2::variant? Regards, &rzej;
On 3/26/19 12:08 PM, Andrzej Krzemienski via Boost wrote: [snip]
As long as there are non-trivial trade-offs for any type/template, there will be reasonable users who would opt for different trade-offs when in different domains. We just have to decide which combinations of the trade-offs are worth collecting into a facility that is present in boost or the standard or elsewhere.
True. And maybe names of different variants of variant should reflect the different trade-offs. Maybe noempty::variant rather than variant2::variant?
What about:
template
On Tue, Mar 26, 2019 at 2:03 PM Larry Evans via Boost
On 3/26/19 12:08 PM, Andrzej Krzemienski via Boost wrote: [snip]
As long as there are non-trivial trade-offs for any type/template, there will be reasonable users who would opt for different trade-offs when in different domains. We just have to decide which combinations of the trade-offs are worth collecting into a facility that is present in boost or the standard or elsewhere.
True. And maybe names of different variants of variant should reflect the different trade-offs. Maybe noempty::variant rather than variant2::variant?
What about:
template
struct boost::variant2 : std::variant { ... }; ?
After all, isn't boost::variant2
simply more restrictive than std::variant in that boost::variant2 has the the never-valueless requirement but std::variant does not.
That cannot work for a variety of reasons. Even if it were possible to implement it that way and we were okay with a dependence on the standard library having std::variant, it also would mean that interactions with the variant via the base class would be able to break the child class's never-empty guarantee (meaning it would not be a guarantee). So an inheritance relationship here would not make sense. -- -Matt Calabrese
On 3/26/19 1:10 PM, Matt Calabrese via Boost wrote:
On Tue, Mar 26, 2019 at 2:03 PM Larry Evans via Boost
wrote: On 3/26/19 12:08 PM, Andrzej Krzemienski via Boost wrote: [snip]
As long as there are non-trivial trade-offs for any type/template, there will be reasonable users who would opt for different trade-offs when in different domains. We just have to decide which combinations of the trade-offs are worth collecting into a facility that is present in boost or the standard or elsewhere.
True. And maybe names of different variants of variant should reflect the different trade-offs. Maybe noempty::variant rather than variant2::variant?
What about:
template
struct boost::variant2 : std::variant { ... }; ?
After all, isn't boost::variant2
simply more restrictive than std::variant in that boost::variant2 has the the never-valueless requirement but std::variant does not. That cannot work for a variety of reasons. Even if it were possible to implement it that way and we were okay with a dependence on the standard library having std::variant, it also would mean that interactions with the variant via the base class would be able to break the child class's never-empty guarantee (meaning it would not be a guarantee). So an inheritance relationship here would not make sense.
Good point. Then how about:
template
On Tue, Mar 26, 2019 at 2:29 PM Larry Evans via Boost
On 3/26/19 1:10 PM, Matt Calabrese via Boost wrote:
That cannot work for a variety of reasons. Even if it were possible to implement it that way and we were okay with a dependence on the standard library having std::variant, it also would mean that interactions with the variant via the base class would be able to break the child class's never-empty guarantee (meaning it would not be a guarantee). So an inheritance relationship here would not make sense.
Good point. Then how about:
template
struct boost::variant2 : private std::variant { using std::variant :: //{ all member functions **not** breaking never-valueless}; //{ over-rides for those member functions that **do** break never-valueless} //} };
I don't think it's realistically implementable that way (need to manipulate index, cases for double-storage, presumed desire to avoid a <variant> dependency, etc.). -- -Matt Calabrese
participants (6)
-
Andrzej Krzemienski
-
dariomt@gmail.com
-
degski
-
Larry Evans
-
Matt Calabrese
-
Peter Dimov