-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Optimization] Don't generate bad_variant_access logic for exhaustive visit using overloaded #74
Comments
I just learned about https://en.cppreference.com/w/cpp/utility/variant/valueless_by_exception so I assume this logic is to implicitly deal with that case — if so, we can close this issue. |
If it is possible to detect that these two cases from the spec are
|
I believe the problem lies in the fact that any type that has a conversion operator to one of the types the variant holds can throw an exception during the conversion, and since that's something that happens independently from the visitation, I can't see how One such examples is given by cppreference itself:
|
Could we only do this optimization when exceptions are disabled?
…On Tue, Feb 16, 2021, 10:30 Fabio ***@***.***> wrote:
I believe the problem lies in the fact that any type that has a conversion
operator to one of the types the variant holds can throw an exception
during the conversion, and since that's something that happens
independently from the variant, I can't see how the variant would possibly
detect that.
One such examples is given by cppreference
<https://en.cppreference.com/w/cpp/utility/variant/valueless_by_exception>
itself:
struct S {
operator int() { throw 42; }
};
std::variant<float, int> v{12.f}; // OK
v.emplace<1>(S()); // v may be valueless
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#74 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFEAU2YFUCSCZGKK5OPLV3S7KTTFANCNFSM4K5V4TEQ>
.
|
Even though they're disabled in the current compilation unit, they might not haven been disabled in the compilation unit that handed you the variant you want to visit, so I guess that's not a check that can be performed. However, a recent Twitter discussion brought to my attention an optimization that has been performed in libstdc++: trivially copyable types aren't able to now put the variant in a valueless state. If mpark's Here's the discussion: https://twitter.com/BarryRevzin/status/1361826113543110657 |
I mean, if -fno-exceptions is set in the compilation unit which #includes
variant.hpp, it's not possible for variant.hpp to *throw* the
bad_variant_access() exception, right? But it still tries to do so:
https://godbolt.org/z/PfPdhn
|
I guess what I'm saying is, if I know in my particular environment that
it's not possible for the variant to be valueless, I expect an exhaustive
std::visit to be equivalent to a switch on an enum (possibly with a
__builtin_unreached() or equivalent afterwards).
…On Thu, Feb 18, 2021 at 1:13 PM Ben Hamilton ***@***.***> wrote:
I mean, if -fno-exceptions is set in the compilation unit which #includes
variant.hpp, it's not possible for variant.hpp to *throw* the
bad_variant_access() exception, right? But it still tries to do so:
https://godbolt.org/z/PfPdhn
|
Huh! I just noticed that somewhere between clang 8 and clang 9, the
std::variant implementation got a whole lot more optimized, and it somehow
elides all the logic for std::bad_variant_access, even if I don't pass
-fno-exceptions:
https://godbolt.org/z/8bT6Ed
So, I guess we can just use std::variant and be happy now. :)
…On Thu, Feb 18, 2021 at 1:26 PM Ben Hamilton ***@***.***> wrote:
I guess what I'm saying is, if I know in my particular environment that
it's not possible for the variant to be valueless, I expect an exhaustive
std::visit to be equivalent to a switch on an enum (possibly with a
__builtin_unreached() or equivalent afterwards).
On Thu, Feb 18, 2021 at 1:13 PM Ben Hamilton ***@***.***>
wrote:
> I mean, if -fno-exceptions is set in the compilation unit which #includes
> variant.hpp, it's not possible for variant.hpp to *throw* the
> bad_variant_access() exception, right? But it still tries to do so:
>
> https://godbolt.org/z/PfPdhn
>
|
Using
clang
from trunk with-std=c++17 -Oz
, the following code usesoverloaded
with an exhaustive set of lambdas to visit all cases of thevariant
:https://godbolt.org/z/k-r72L
Even though the lambdas exhaustively handle all cases, MPark.Variant still generates error handling logic to throw
bad_variant_access
exceptions (which as far as I can tell should never happen).I think it'd be a nice optimization to drop the error handling entirely if the visitation is exhaustive.
Here's the current state of the optimized assembly in case this gets fixed:
The text was updated successfully, but these errors were encountered: