为什么 C++17 的 std::any 不允许 any_cast 返回一个可移动的值?

Why does C++17's std::any not allow returning a movable value by any_cast?

在根据可用规范 in this Wiki 实现 C++17 的 std::any 时,我偶然发现了一些对我来说似乎荒谬的东西:

自由函数 std::any_cast

In the definition,用于从 std::any 实例中检索值,r-value[=38= 的重载] 提供参考文献(这是第三个):

template< class ValueType >
ValueType any_cast(any&& operand); // (3)

现在,概要下方列出了适用于重载 2 和 3 的要求(这意味着还包括右值重载):

2-3) Returns *any_cast<std::remove_reference_t<ValueType>>(&operand)

定义似乎实际上不允许移动数据!

函数调用只是重定向到基于指针的重载;有关 operand 临时性质的信息丢失了!

是不是有意让我不能搬出any实例?这只是维基中的一个错误吗?我错了吗?

不需要复制的std::any实现是完全可以做到的。只有一个问题:当用户请求 std::any 的副本时,你会怎么做?这个问题的一个解决方案是让 std::any 只移动,另一个是如果底层类型是只移动,让它在复制构造函数上抛出异常,还有一个是要求能够复制底层类型.选择了第三种方案。

ValueType 可复制构造的要求非常好 - 因为不可复制构造的类型不可能存储在 std::any 实例中,std::any_cast 可能作为好吧,让一个总是失败的转换成为编译器错误。

现在,ValueType any_cast(any&& operand) 的实现不允许移动这一事实似乎是一种疏忽 - 毕竟,副本是移动的完美实现,并且实现可以自由委托如果移动构造函数存在,则作业到移动构造函数,如果不存在,则复制构造函数。

在撰写本文时,问题处于 WP 状态,which means

WP - (Working Paper) - The proposed resolution has not been accepted as a Technical Corrigendum, but the full WG21/PL22.16 committee has voted to apply the Defect Report's Proposed Resolution to the working paper.

在此处查看 lwg 以获取更多信息:http://wg21.cmeerw.net/lwg/issue2509

提议的决议确实是

For the third form, if is_move_constructible_v<ValueType> is true and is_lvalue_reference_v<ValueType> is false, std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise, *any_cast<remove_reference_t<ValueType>>(&operand)

以及列出 WP 的缺陷报告列表:http://cplusplus.github.io/LWG/lwg-defects.html#2509