Description
Describe the bug
The order of the template parameters in variant influences if the destructor is a constant expression.
I think it might be related to a compiler behaviour/bug with constexpr destructors being weird with unions.
It seems that it requires the very first element to have a constexpr
destructor in order for the whole object to have a constexpr
destructor.
From playing around it also seems like you're using the only case where this even works at all on msvc: recursive templates where the outer-most case is the first union field and has a constexpr
destructor.
Command-line test case
https://godbolt.org/z/h5b766seM
#include <variant>
struct Trivial {};
struct NonTrivial {
NonTrivial() {}
~NonTrivial() {}
};
// Trivial first
constexpr std::variant<Trivial, NonTrivial> v0{Trivial{}};// no error
// Nontrivial first
constexpr std::variant<NonTrivial, Trivial> v1{Trivial{}};// error
Expected behavior
I would expect it to either error on both, or error on neither
STL version
It becomes an issue since VS16.11 up until the latest on godbolt (idk specifically which stl version that is sorry)
Before that both are errors so its not a problem I guess
Additional context
There are 4 potential solutions I could think of:
- Say the current behaviour is intended (strange but potentially only good option)
- Make this invalid in both cases (don't do this please)
- Somehow fix the msvc compiler to make the destructor constexpr-ness not be so weird
- Detect if there is a constexpr destructable member in some outer template, and reorder the template for storage so that the constexpr one is always first. But I don't know if this would be possible and still remain standard compliant and not break abi (I suspect it would break both)