Consider:
#include <variant>
struct A { 
  A() = default;
  A(A&&) = delete;
};
struct B { 
  B() = delete;
  B(A&&) {};
};
int main() {
  std::variant<A, B> v{};
  v = A{};
}
MSVC accepted it, while GCC and Clang rejected it with the same error message:
opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/variant:1465:3: error: call to deleted member function 'operator='
                operator=(variant(std::forward<_Tp>(__rhs)));
                ^~~~~~~~~
<source>:15:5: note: in instantiation of function template specialization 'std::variant<A, B>::operator=<A>' requested here
  v = A{};
    ^
Which compiler should I trust?
EDIT
Initially, there was no language-lawyer tag, which was why I used cppreference for the analysis. However, looking into the latest draft (relevant section), I don't see anything that would make it invalid.
I believe MSVC is incorrect. According to the documentation:
- Converting assignment.
 
Determines the alternative type
T_jthat would be selected by overload resolution for the expressionF(std::forward<T>(t))if there was an overload of imaginary functionF(T_i)for everyT_ifromTypes...in scope at the same time, except that:
- An overload
 F(T_i)is only considered if the declarationT_i x[] = { std::forward<T>(t) };is valid for some invented variablex;
With some imaginary function having forwarding reference parameter and calling it with A{} argument, A x[] = { std::forward<T>(t) }; is not valid while B x[] = { std::forward<T>(t) }; is. Consequently , T_j should be resolved as B. Live demo: https://godbolt.org/z/fM67e7oGj.
Then:
- If
 *thisalready holds aT_j...
This does not apply, since v does not hold a B.
Next:
- Otherwise, if
 std::is_nothrow_constructible_v<T_j, T> || !std::is_nothrow_move_constructible_v<T_j>istrue...
This also does not apply, since this expression is false; live demo: https://godbolt.org/z/x674rnbcj (and, MSVC agrees on that: https://godbolt.org/z/5Techn8jG).
Finally:
- Otherwise, equivalent to
 this->operator=(variant(std::forward<T>(t))).
However, this call does not compile with MSVC: https://godbolt.org/z/cWr4f6EhK.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With