You forgot about one of the most important reasons why we got make_unique . Consider the difference between these two function calls:
some_function(make_unique<T>(), std::vector<U>{1, 2, 3}); some_function(unique_ptr(new T()), std::vector<U>{1, 2, 3});
One of these functions has a subtle error. Can you guess what it is?
If the vector constructor throws, then something really bad can happen. Due to the rules for evaluating the expression of the arguments of a C ++ function, it is possible that the evaluation order may be new T() , followed by std::vector<U>{1, 2, 3} , followed by the unique_ptr<T> constructor. If vector throws, then the new ed pointer is never freed.
This is bad. And this is about 90% of the reasons why we have make_unique in general.
Now, having said that, C ++ 17 also makes changes to the evaluation of function argument expressions, which makes this point obsolete. C ++ 17 rules guarantee that there can be no match between the various expressions that initialize the arguments. That is, each argument initializer expression completes completely before the other starts. C ++ 17 does not guarantee the order in which arguments are expressed, but there can be no alternation between subexpressions.
In the above code, the evaluation order can be first vector or new T() . But if he first evaluates new T() , he must evaluate unique_ptr<T>() before evaluating the vector constructor.
So, in C ++ 17, both of them are safe. Thus, although the output of the template argument is not deprecated by make_unique , C ++ 17 generally does.
Of course, there is always the problem of standard matching. The compiler can implement the output of the constructor argument before implementing the rules for ordering the evaluation of an expression. And there is no way to make your code broken if the evaluation order of the expression does not exist (unless you rely on function validation macros that some compilers do not support).
To be safe, I suggest sticking with make_unique in such circumstances.
And finally, there is a feature of make/allocate_shared : the ability to allocate a control unit and an object in the same store. This is not an insignificant feature of shared_ptr , and it cannot be replicated using the new template.
Therefore, you should continue to use make_shared , if possible.