Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::unique_ptr not permit type inference?

It would be easier to read/write the second line of my example since the type of the template argument is obvious:

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

Of course, if you want to use polymorphism, we could always write:

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

What is the reason for such a constraint?

like image 590
Boiethios Avatar asked Dec 15 '16 11:12

Boiethios


People also ask

Can unique_ptr be assigned?

It can be assigned: class owner { std::unique_ptr<someObject> owned; public: owner() { owned=std::unique_ptr<someObject>(new someObject()); } };

Can you copy unique_ptr?

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.

What is std :: unique_ptr?

std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

What happens when unique_ptr goes out of scope?

unique_ptr. An​ unique_ptr has exclusive ownership of the object it points to and ​will destroy the object when the pointer goes out of scope.

Is it possible to use unique_ptr in a class?

You can, of course, use std::unique_ptr as a composition member of your class. This way, you don’t have to worry about ensuring your class destructor deletes the dynamic memory, as the std::unique_ptr will be automatically destroyed when the class object is destroyed.

Can we assign a unique_ptr object to another smart pointer?

We can not assign a std::unique_ptr object to another smart pointer. std::unique_ptr disposes the managed object when the unique_ptr goes out of context or is assigned with nullptr. It takes care of the common mistake that programmers make of forgetting to delete dynamically allocated objects.

What is unique_ptr in C++11?

std::unique_ptr is the C++11 replacement for std::auto_ptr. It should be used to manage any dynamically allocated object that is not shared by multiple objects.

How do you convert a derived class to a unique_ptr?

If T is a derived class of some base B, then std::unique_ptr<T> is implicitly convertible to std::unique_ptr<B>. The default deleter of the resulting std::unique_ptr<B> will use operator delete for B, leading to undefined behavior unless the destructor of B is virtual.


2 Answers

This is not an issue that's... unique to std::unique_ptr - instantiation of template classes does not automatically deduce the types from the constructors previous to C++17. This is why facilities such as std::make_unique, std::make_pair and std::make_tuple exist: they use template function argument deduction to reduce boilerplate.


In C++17 you will be able to write:

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

thanks to class template deduction - assuming P0433R0 is accepted, which adds a deduction guide to std::unique_ptr.

The deduction guide is required because std::unique_ptr's constructor that takes a raw pointer uses the pointer type alias which is defined as follows:

std::remove_reference<Deleter>::type::pointer if that type exists, otherwise T*. Must satisfy NullablePointer.

Type aliases like pointer are non-deducible contexts, so P0433R0 proposes the addition of:

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

Which would enable class template deduction for std::unique_ptr.

like image 138
Vittorio Romeo Avatar answered Sep 22 '22 09:09

Vittorio Romeo


The real reason for the absense of the deduction guides is this:

There is no class template argument deduction from pointer type because it is impossible to distinguish a pointer obtained from array and non-array forms of new

Side note: The other answer promised that c++17 will allow this to compile:

This is simply not the case. Also For the above reason.

like image 32
sehe Avatar answered Sep 19 '22 09:09

sehe