2016-12-15 6 views
9

Все в названии. Было бы легче читать/писать вторую строку моего примера, так как тип аргумента шаблона очевидна:Почему std :: unique_ptr не допускает вывода типа?

#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()); 

В чем причина такого ограничения?

+7

Используйте 'std :: make_unique' (C++ 14), так что повторений нет. – Jarod42

ответ

21

Это не проблема, которая уникальна для std::unique_ptr - экземпляр классов шаблонов автоматически не выводит типы из конструкторов, предшествующих C++ 17. Вот почему такие объекты, как std::make_unique, std::make_pair и std::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<Deleter>::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.

+1

Хороший ответ, но должен указать, что хотя 'std :: make_unique (...)' действительно уменьшает шаблон, он может выводить только типы аргументов в '' '' '' '' '' '' '' '' '' '' ', выведите «ARGS ...». – KyleKnoepfel