我可以在对 std::visit 的调用中更改 std::variant 中的保留类型吗

May I change the held type in a std::variant from within a call to std::visit

以下代码是否调用了未定义的行为?

std::variant<A,B> v = ...;

std::visit([&v](auto& e){
  if constexpr (std::is_same_v<std::remove_reference_t<decltype(e)>,A>)
    e.some_modifying_operation_on_A();
  else {
    int i = e.some_accessor_of_B();
    v = some_function_returning_A(i); 
  }
}, v);

特别是,当变体不包含 A 时, 此代码重新分配 A,同时仍然持有对先前持有的 B 类型对象的引用。 但是,由于在分配后不再使用引用, 我觉得代码没问题。 但是,标准库是否可以免费实施 std::visit 以上是未定义的行为?

代码没问题。

std::visit 的规范中没有要求访问者不更改调用它的任何变体的备选方案。唯一的要求是:

Requires: For each valid pack m, e(m) shall be a valid expression. All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.

您的访问者是每个 m 的有效表达式,并且总是 returns void,因此它满足要求并具有明确定义的行为。