首页 > 解决方案 > 为什么 std::is_move_constructible ::value == false 尽管 S 移动构造很好?什么是正确的行为?

问题描述

标签: c++c++11c++17move-semanticsmove-constructor

解决方案


尽管该标准认为S(const S&&)是“移动构造函数”并且您可能认为这将结束,但is_move_constructible实际上要求您的声明s3在 C++14 及更早版本中有效;即将为该声明选择一个移动构造函数。

从 cppref

如果T不是可引用类型(即,可能是cv-qualified void或具有cv-qualifier-seqref-qualifier的函数类型),则提供等于 的成员常量值false。否则,提供一个等于 的成员常量值std::is_constructible<T, T&&>::value

您遇到的问题是S(S&&)仍然可以通过重载决议找到。发生这种情况,S(S&&)S(const S&&),更好的匹配S(S&&)被发现被删除。

s3的声明在 C++17 中有效,只是因为它根本没有复制或移动。过去是临时的“声明”,现在只是一个奇特的构造函数参数列表;当且仅当根本需要一个匹配的临时文件时,它才会在调用堆栈的下方被“物化”。这被称为“保证省略”,即使没有真正被省略,因为它根本不存在。

请记住,移动语义是一种错觉;您真正要做的就是让语言“调用函数”,并为您作为参数提供的表达式提供适当的参数。s2之所以有效,是因为您传递了一个右值 const S(通过提供 a 形成的表达式的值类别和类型const S&&),它可以绑定到 a const S&&(但不能绑定到a S&&!);这是否算作“移动构建就好了”是一个观点问题。

tl; dr:该特征需要S(S&&)起作用,而您明确将其定义为不起作用。


推荐阅读