【问题标题】:Why does std::unique_ptr not permit type inference?为什么 std::unique_ptr 不允许类型推断?
【发布时间】:2016-12-15 11:19:00
【问题描述】:

由于模板参数的类型很明显,因此读/写示例的第二行会更容易:

#include <memory>

struct Foo{};

int main()
{
  // redundant: good
  auto foo1 = std::unique_ptr<Foo>(new Foo());
  // without explicitness: does not compile
  auto foo2 = std::unique_ptr(new Foo());
}

当然,如果你想使用多态,我们总是可以这样写:

auto base = std::unique_ptr<Base>(new Derived());

这种约束的原因是什么?

【问题讨论】:

  • 使用std::make_unique (c++14),所以不再重复。

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


【解决方案1】:

这不是std::unique_ptr 独有的问题 - 模板类 的实例化不会自动从 C++17 之前的构造函数中推断出类型。这就是std::make_uniquestd::make_pairstd::make_tuple 等设施存在的原因:它们使用模板函数参数推导来减少样板。


在 C++17 中,您将能够编写:

auto foo2 = std::unique_ptr(new Foo());

感谢class template deduction - 假设P0433R0 被接受,这为std::unique_ptr 添加了一个演绎指南

因为std::unique_ptr's constructor that takes a raw pointer使用了pointer类型别名,所以需要推导指南,定义如下:

std::remove_reference&lt;Deleter&gt;::type::pointer 如果该类型存在,否则为T*。必须满足NullablePointer

pointer 这样的类型别名是不可演绎的上下文,因此 P0433R0 建议添加:

template<class T> unique_ptr(T*) 
    -> unique_ptr<T, default_delete<T>>;

template<class T, class V> unique_ptr(T*, V) 
    -> unique_ptr<T, default_delete<T, V>>;  

template<class U, class V> unique_ptr(U, V) 
    -> unique_ptr<typename pointer_traits<typename V::pointer>::element_type, V>;  

这将为std::unique_ptr 启用类模板推导

【讨论】:

  • 很好的答案,但应该指出,虽然std::make_unique&lt;T,ARGS...&gt;(...) 确实减少了样板,但它只能推断T 的c'tor 的参数类型——即它只能推断出ARGS....
  • 根据 [unique.ptr.single.ctor] 中的 C++17 草案 n4750 类模板推导不正确:If class template argument deduction (16.3.1.8) would select the function template corresponding to this constructor, then the program is ill-formed.
  • 我认为这个答案已经过时了?没有添加扣除指南,这是有充分理由的。我添加了自己的答案,但也许修改一下这个答案会很好。
【解决方案2】:

演绎指南缺失的真正原因是这样的:

指针类型没有类模板参数推导because it is impossible to distinguish a pointer obtained from array and non-array forms of new

旁注:另一个答案承诺 c++17 将允许编译:

事实并非如此。也是出于以上原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多