自定义类型 std::variant 的赋值运算符删除了特殊成员函数?

Assignment operator of std::variant of custom type with deleted special member functions?

考虑:

#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 接受了它,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{};
    ^

我应该信任哪个编译器?

编辑

最初,没有language-lawyer标签,这就是为什么我使用cppreference进行分析的原因。但是,查看最新草案 (relevant section),我没有发现任何会使它无效的内容。


我认为 MSVC 不正确。根据 documentation:

  1. Converting assignment.
  • Determines the alternative type T_j that would be selected by overload resolution for the expression F(std::forward<T>(t)) if there was an overload of imaginary function F(T_i) for every T_i from Types... in scope at the same time, except that:

    • An overload F(T_i) is only considered if the declaration T_i x[] = { std::forward<T>(t) }; is valid for some invented variable x;

对于一些具有转发引用参数并使用 A{} 参数调用它的虚构函数,A x[] = { std::forward<T>(t) }; 无效而 B x[] = { std::forward<T>(t) }; 有效。因此,T_j 应该解析为 B。现场演示:https://godbolt.org/z/fM67e7oGj.

然后:

  • If *this already holds a T_j...

这不适用,因为 v 不包含 B

下一个:

  • Otherwise, if std::is_nothrow_constructible_v<T_j, T> || !std::is_nothrow_move_constructible_v<T_j> is true...

这也不适用,因为这个表达式是false;现场演示:https://godbolt.org/z/x674rnbcj (and, MSVC agrees on that: https://godbolt.org/z/5Techn8jG).

最后:

  • Otherwise, equivalent to this->operator=(variant(std::forward<T>(t))).

但是,此调用无法使用 MSVC 进行编译:https://godbolt.org/z/cWr4f6EhK