https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113007

            Bug ID: 113007
           Summary: `std::variant` converting constructor and `operator=`
                    compile while the C++ Standard says they must not
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: paul.skeptic at yandex dot ru
  Target Milestone: ---

According to [variant.ctor] (https://eel.is/c++draft/variant.ctor, also see
https://en.cppreference.com/w/cpp/utility/variant/variant) converting
constructor

    template<class T>
    constexpr variant(T&& t) noexcept(/*...*/);

determines the alternative to construct as if by selecting an overload for
`F(std​::​forward<T>(​t))` from an overload set `F(T_j)` where `T_j` are types
of the alternatives,
e.g. for `std::variant<std::monostate, bool, int64_t, double>` the overload set
would be

    void F(std::monostate) {}
    void F(bool) {}
    void F(int64_t) {}
    void F(double) {}


In violation of the standard this code compiles with GCC and libstdc++
(https://godbolt.org/z/fd8xa1bqM):

    std::variant<std::monostate, bool, int64_t, double> v = 42;

while overload resolution of `F()` fails:

    F(42); // error: ambiguous confused_john_travolta.gif

Compiler output:

<source>: In function 'int main()':
<source>:14:4: error: call of overloaded 'F(int)' is ambiguous
   14 |   F(42);
      |   ~^~~~
<source>:6:6: note: candidate: 'void F(bool)'
    6 | void F(bool) {}
      |      ^
<source>:7:6: note: candidate: 'void F(int64_t)'
    7 | void F(int64_t) {}
      |      ^
<source>:8:6: note: candidate: 'void F(double)'
    8 | void F(double) {}
      |      ^


Also the same applies to converting assignment operator

    template<class T>
    constexpr variant& operator=(T&& t) noexcept(/*...*/);

see [variant.assign] (https://eel.is/c++draft/variant.assign, also
https://en.cppreference.com/w/cpp/utility/variant/operator%3D).

Among libc++, libstdc++ and MSVC standard libraries only MSVC standard library
gets it according to the standard so you can look at it for reference.

See corresponding bug for libc++:
https://github.com/llvm/llvm-project/issues/75323

Reply via email to