不可移动的C ++ 17唯一指针

时间:2018-11-24 06:08:17

标签: c++ c++11 c++17 unique-ptr

我遇到了这个答案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进行试用。

3 个答案:

答案 0 :(得分:17)

p不是const。请参见here,以免它无法按预期的方式运行。

auto的推论与template<class T>void foo(T)相似。 T从不推论为constauto p=也不推论。

同时,auto p =行有效,因为您以模式进行了编译。在 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