[英]How could type, comprising non move constructible field, be move constructible?
这是这个问题的根源
在使用clang ++ / libc ++和g ++ / libstdc ++编译以下代码时,我有不同的行为。
#include <type_traits>
#include <utility>
#include <iostream>
int main()
{
using array_t = int[42];
std::cout << "array_t:" << std::endl;
std::cout << " is_move_constructible: " << std::is_move_constructible<array_t>::value << std::endl;
std::cout << " is_move_assignable: " << std::is_move_assignable<array_t>::value << std::endl;
std::cout << std::endl;
using pair_t = std::pair<array_t, array_t>;
std::cout << "pair_t:" << std::endl;
std::cout << " is_move_constructible: " << std::is_move_constructible<pair_t>::value << std::endl;
std::cout << " is_move_assignable: " << std::is_move_assignable<pair_t>::value << std::endl;
std::cout << std::endl;
pair_t p1;
pair_t p2(std::move(p1));
return 0;
}
lang声(失败):
In file included from /home/soon/Src/C++/main/main.cpp:2:
/usr/include/c++/v1/utility:283:11: error: array initializer must be an initializer list
: first(_VSTD::forward<first_type>(__p.first)),
^
/home/soon/Src/C++/main/main.cpp:20:12: note: in instantiation of member function 'std::__1::pair<int [42], int [42]>::pair' requested here
pair_t p2(std::move(p1));
^
In file included from /home/soon/Src/C++/main/main.cpp:2:
/usr/include/c++/v1/utility:284:11: error: array initializer must be an initializer list
second(_VSTD::forward<second_type>(__p.second))
^
g ++编译没有错误。 输出为:
array_t:
is_move_constructible: 0
is_move_assignable: 0
pair_t:
is_move_constructible: 1
is_move_assignable: 1
我无法确定,这是正确的。 我猜想,如果一个类包含不可移动构造的字段,则不能使用移动技术来构造它。 那是对的吗?
我不知道GCC(或更确切地说libstdc ++)是否允许使用此代码,但是如果是这样,那么结果是正确的。 如果所有成员都具有自己的move构造函数或可以被简单复制,则将生成默认的move构造函数。 Pair的move构造函数被指定为默认值,因此它遵循以下规则。 它们的基元和数组都是可复制的。
我怀疑libstdc ++是正确的,由于某种原因,您正在libc ++中进入_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
的编译器兼容性分支,该分支不支持数组,因为它不使用= default
。 您正在使用什么版本的Clang,并且正确指定了-std=c++11
?
我应该补充一下塞巴斯蒂安的答案,即clang-3.3编译没有问题的代码,其结果(在运行时)与gcc相同。 因此,您的clang编译器版本的不当行为似乎是一个错误,目前已修复。
类型特征可能有些棘手。 is_move_constructible/assignable
检查类型是否包含移动构造函数/赋值运算符(显式或隐式定义)。 而已。 这些类型特征无法检测到这些构造函数/运算符的实际实例是否格式错误。
由于std::pair
包含移动构造函数/赋值运算符,因此is_move_constructible
和is_move_assignable
都将为std::true_type
。 这仅表示已定义它们,但这并不意味着您可以实际使用它们。
这已经在讨论这个线程 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.