我遇到了这个答案Prevent moving of a unique_ptr C++11。但是,当在联机编译器上尝试使用它时,此方法适用于C ++ 11(std::move
编译器错误),但适用于C ++ 17,我看到下面的std::move
成功。编译器不应该在该行上抛出错误吗?另外,如果C ++ 17中的某些语义发生了变化,那么在C ++ 17及更高版本中创建不可移动的unique_ptr的正确方法是什么。
template <typename T>
using scoped_ptr = const std::unique_ptr<T>;
int main()
{
auto p = scoped_ptr<int>(new int(5));
auto p2 = std::move(p); // should be error?
std::cout << *p2 << std::endl; // 5
return 0;
}
您可以在线here进行试用。
答案 0 :(得分:17)
p
不是const
。请参见here,以免它无法按预期的方式运行。
auto
的推论与template<class T>void foo(T)
相似。 T
从不推论为const
,auto p=
也不推论。
同时,auto p =
行有效,因为您以c++17模式进行了编译。在c++11 it does not compile中。这是因为prvalue在17中有何不同?有人称差异保证省略。
如果您想要一个固定的唯一ptr:
template<class T, class D>
struct immobile_ptr:private std::unique_ptr<T, D>{
using unique_ptr<T>::operator*;
using unique_ptr<T>::operator->;
using unique_ptr<T>::get;
using unique_ptr<T>::operator bool;
// etc
// manually forward some ctors, as using grabs some move ctors in this case
};
template<class T, class...Args>
immobile_ptr<T> make_immobile_ptr(Args&&...args); // todo
另一种选择是使用不动的驱逐舰获得独特的ptr。
template<class X>
struct nomove_destroy:std::destroy<T>{
nomove_destroy(nomove_destroy&&)=delete;
nomove_destroy()=default;
nomove_destroy& operator=(nomove_destroy&&)=delete;
};
template<class T>
using nomove_ptr=std::unique_ptr<T,nomove_destroy<T>>;
但是我不确定是否可行。
答案 1 :(得分:3)
请注意,p
被声明为非引用类型,参数const
的{{1}}部分在类型推导中被忽略。那么scoped_ptr<int>(new int(5))
的类型推导结果是p
,而不是std::unique_ptr<int>
(即您所期望的const std::unique_ptr<int>
)。
您想要的可能是
scoped_ptr<int>
答案 2 :(得分:3)
欢迎使用C ++中的类型推导的世界。尝试
auto & p = scoped_ptr<int>(new int(5));
或
auto && p = scoped_ptr<int>(new int(5));
相反。本讲座可能会有所帮助:https://www.youtube.com/watch?v=wQxj20X-tIU