次のコードは未定義の振る舞いを呼び出しますか?
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:有効なパックごとに
m
、e(m)
は有効な式でなければなりません。そのような式はすべて、同じタイプと値のカテゴリでなければなりません。そうしないと、プログラムの形式が正しくありません。
ビジターは各m
の有効な式であり、常にvoid
を返すため、要件を満たし、明確に定義された動作をします。