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

时间:2016-07-25 16:52:35

标签: c++ std move-semantics c++17

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

自由函数std::any_cast

In the definition,用于从std::any实例检索值,提供 r-value 引用的重载(它是第三个):

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

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

  

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

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

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

我是否打算离开任何一个实例?这只是维基中的一个错误吗?我错了吗?

2 个答案:

答案 0 :(得分:10)

在撰写此问题时,问题出现在 WP 状态,which means

  WP - (工作文件) - 提议的决议未作为技术勘误表被接受,但WG21 / PL22.16全体委员会已投票决定将缺陷报告的建议决议应用于工作文件。 / p>

有关详细信息,请参阅lwg:http://wg21.cmeerw.net/lwg/issue2509

提议的决议确实是

  

对于第三种形式,如果is_move_constructible_v<ValueType>为真且is_lvalue_reference_v<ValueType>为假,std::move(*any_cast<remove_reference_t<ValueType>>(&operand)),则为*any_cast<remove_reference_t<ValueType>>(&operand)

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

答案 1 :(得分:0)

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

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

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