在尝试使用不可复制(私有拷贝构造函数)但可移动对象时,我得到了编译错误,g++ (GCC) 4.7.2但没有.对我来说,我的例子看起来与SO和其他地方的许多其他例子相同.错误消息使得它看起来像结构不是"可直接构造"的问题 - 我不知道这意味着什么所以我更加不确定为什么一个对象需要被"直接构造"才能被推回.MSVC-2012std::vector::push_back
#include <vector>
#include <memory>
struct MyStruct
{
MyStruct(std::unique_ptr<int> p);
MyStruct(MyStruct&& other);
MyStruct& operator=(MyStruct&& other);
std::unique_ptr<int> mP;
private:
// Non-copyable
MyStruct(const MyStruct&);
MyStruct& operator=(const MyStruct& other);
};
int main()
{
MyStruct s(std::unique_ptr<int>(new int(5)));
std::vector<MyStruct> v;
auto other = std::move(s); // Test it is moveable
v.push_back(std::move(other)); // Fails to compile
return 0;
}
Run Code Online (Sandbox Code Playgroud)
给出错误
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/type_traits: In instantiation of ‘struct std::__is_direct_constructible_impl<MyStruct, const MyStruct&>’:
... snip ...
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:900:9: required from ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = MyStruct; _Alloc = std::allocator<MyStruct>; std::vector<_Tp, _Alloc>::value_type = MyStruct]’
main.cpp:27:33: required from here
main.cpp:16:5: error: ‘MyStruct::MyStruct(const MyStruct&)’ is private
Run Code Online (Sandbox Code Playgroud)
各种答案的简单解决方法:
MyStruct(const MyStruct&) = delete;而不是private ctor黑客boost::noncopyable(或其他具有私有ctor的类)Jon*_*ely 13
失败是由于G ++ 4.7的限制,它没有实现DR 1170,后者在C++ 11标准化过程中很晚才改变,说访问检查应该作为模板参数推导的一部分来完成.
根本原因是libstdc ++ vector将移动元素,如果移动操作保证不抛出(即它被声明noexcept或throw()),否则如果类型是可复制的,元素将被复制,否则如果类型不可复制但确实有 -抛出移动操作然后它将被移动(如果抛出异常,结果是未定义的未定义.)这是通过检查is_nothrow_move_constructible和is_copy_constructible类型特征来实现的.在您的情况下,类型不是不可移动构造,因此is_copy_constructible检查特征.你的类型有一个拷贝构造函数,但是它不可访问,因此is_copy_constructible特征会产生G ++ 4.7的编译器错误,因为在模板参数推导期间没有进行访问检查.
如果你移动构造函数和移动赋值运算符,noexcept那么类型将被移动并且不需要是可复制的,因此is_copy_constructible不使用失败的特征,并且代码编译好.
或者,(如评论中所述)如果您删除了复制构造函数,那么该is_copy_constructible特征将获得正确的结果.
另一个替代方法是使用类似boost::noncopyable隐藏的方式使复制构造函数被删除以便is_copy_constructible特征正常工作(并且也适用于不支持已删除函数的MSVC等较旧的编译器).我不知道你是什么意思让它找不到错误,MSVC没有向你展示编译器错误的完整上下文吗?
结论:在适当的地方使用unique_ptr但不要使类明确地移动
我不同意这个结论,这太极端了.相反,尽可能让你的课程无法移动.此外,如果可能,使用已删除的函数使类型不可复制而不是私有+未实现的函数,可能使用宏来移植到较旧的编译器,例如
#if __cplusplus >= 201103L
#define NONCOPYABLE(TYPE) \
TYPE(const TYPE&) = delete; TYPE& operator=(const TYPE&) = delete
#else
// must be used in private access region
#define NONCOPYABLE(TYPE) \
TYPE(const TYPE&); TYPE& operator=(const TYPE&)
#endif
struct MyStruct
{
...
private:
NONCOPYABLE(MyStruct);
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2921 次 |
| 最近记录: |