根据可用的规范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
临时性质的信息丢失了!
我是否打算离开任何一个实例?这只是维基中的一个错误吗?我错了吗?
答案 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)
的实现不允许移动这一事实似乎是一种疏忽 - 毕竟,副本是一个完美的移动实现,并且实现可以自由地将作业委托给移动构造函数,如果它在那里,并复制构造函数,如果没有。