The emplace versions emplace not create an object of the required type at all under the circumstances of the exception. This may result in an error.
Consider the following example, which uses just std::vector for convenience (assume that uptr behaves like std::unique_ptr , except that the constructor is not explicit):
std::vector<uptr<T>> vec; vec.push_back(new T());
This is safe for exceptions. A temporary uptr<T> is created to go to push_back , which moves to the vector. If the redistribution of the vector fails, the highlighted T still belongs to the smart pointer, which correctly deletes it.
Compare with:
std::vector<uptr<T>> vec; vec.emplace_back(new T());
emplace_back not allowed to create a temporary object. ptr will be created once, in place in the vector. If redistribution fails, there is no place to create in place, and no smart pointer will ever be created. T will leak.
Of course, the best alternative is:
std::vector<std::unique_ptr<T>> vec; vec.push_back(make_unique<T>());
which is equivalent to the first, but makes the creation of a smart pointer explicit.
Ben voigt
source share