microsoft / microsoft/STL

<variant>: `std::variant` template param order determines if destructor is constant expression

Open
#5,329 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug compiler
Dominant language
C++
Stars
11.2k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

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:

  1. Say the current behaviour is intended (strange but potentially only good option)
  2. Make this invalid in both cases (don't do this please)
  3. Somehow fix the msvc compiler to make the destructor constexpr-ness not be so weird
  4. 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)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked Compiler Explorer test case and the std::variant destructor behavior for the two template-parameter orders. Investigate whether the difference is caused by the MSVC compiler or STL implementation; done means documenting the intended behavior and agreeing on a resolution or fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.