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

Non-Movable C++17 Unique Pointer

我看到了这个答案 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

注意p被声明为非引用类型,参数scoped_ptr<int>(new int(5))const部分在类型推导中被忽略。那么p的类型推导结果是std::unique_ptr<int>,而不是const std::unique_ptr<int>(即如你所料的scoped_ptr<int>)。

你想要的可能是

auto& p = scoped_ptr<int>(new int(5)); // p is of type const std::unique_ptr<int>& now

p 不是 const。请参阅 here 以了解它是否按照您预期的方式失败。

autotemplate<class T>void foo(T) 一样推导。 T 永远不会被推断为 constauto p= 也不会。

同时,auto p = 行有效,因为您在 mode. In it does not compile 中编译了它。这是因为纯右值在 17 中有何不同;有些人称差异保证省略。

如果你想要一个固定的唯一指针:

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>>;

但我不确定这是否有效。

欢迎来到 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