This是此问题的根源
使用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;
}
铛(失败):
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
我无法确定,哪个是正确的。我猜,如果一个类包含非移动可构造字段,则无法使用移动技术构造它。这是对的吗?
答案 0 :(得分:1)
我不知道GCC(或者更确切地说是libstdc ++)是否正确允许此代码,但如果是,则结果是正确的。如果所有成员都有自己的移动构造函数,或者通常可以复制,则将生成默认的移动构造函数。 Pair的移动构造函数被指定为默认值,因此它遵循这些规则。它们的基元和数组都是可以复制的。
我怀疑libstdc ++是正确的,并且出于某种原因,你在libc ++中为_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
输入了编译器兼容性分支,它不支持数组,因为它不使用= default
。您使用的是哪个版本的Clang,是否正确指定了-std=c++11
?
答案 1 :(得分:1)
我应该补充塞巴斯蒂安的答案,即clang-3.3用与gcc相同的结果(在运行时)编译你的代码没有问题。因此,您的clang编译器版本的错误行为似乎是一个错误,现在已经修复了。
答案 2 :(得分:1)
类型特征可能有点棘手。 is_move_constructible/assignable
检查类型是否包含移动构造函数/赋值运算符(显式或隐式定义)。而已。那些类型特征将不会检测那些构造函数/运算符的实际实例是否形成不良。
由于std::pair
包含移动构造函数/赋值运算符,因此is_move_constructible
和is_move_assignable
都将为std::true_type
。这只表明它们已被定义,但这并不意味着您可以实际使用它们。
这已在this thread中讨论过。