How to implement make_unique function in C++11?
Copied from make_unique and perfect forwarding (the same is given in Herb Sutter's blog)
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
If you need it in VC2012, see Is there a way to write make_unique() in VS2012?
Nevertheless, if the solution in sasha.sochka's answer compiles with your compiler, I would go with that one. That is more elaborate and works with arrays as well.
Why does C++11 have `make_shared` but not `make_unique`
According to Herb Sutter in this article it was "partly an oversight". The article contains a nice implementation, and makes a strong case for using it:
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
Update: The original update has been updated and the emphasis has changed.
Why I cannot pass std::make_unique S as a function parameter?
The signature for std::make_unique
is
template<class T, class... Args>
unique_ptr<T> make_unique(Args&& ...args);
If you call make_unique
directly the compiler is using template argument deduction to deduce what Args
should be from what you are invoking it with. By passing std::make_unique<S>
to your function, you are stating that Args
is an empty parameter pack, and therefore std::make_unique
is expecting zero parameters and tries to default construct an S. It is the same as calling std::make_unique<S>();
directly.
Extending namespace std to implement make_unique when using C++11
No, this is forbidden—even though, via
#define make_unique ? ? ?
a conforming C++11 program can be quite sure that the library never mentions the name (outside of a stringization) and would thus be unable to detect the extension.
How to create a wrapper for `std::make_unique T `?
You need to forward properly the values, and you need to expand the pack.
First, make it compile:
template<typename T, typename... Args>
UniquePtr<T> MakeUnique(Args... args) // not recursive
{ // ^---- no need for <T> when defining function template
return std::make_unique<T>(args...); // the ... expands the pack
}
Then, you need to forward, because args...
will copy everything. You want to move rvalues, and copy lvalues:
template<typename T, typename... Args>
UniquePtr<T> MakeUnique(Args&&... args)
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
Can std::make_unique take the output of a function as an argument?
Is there a way to use make_unique and pass the output of a function as a parameter?
std::make_unique<T>
takes constructor arguments to create a new T
. It does not take a T*
to an existing T
.
Furthermore, you can't specify a deleter with it like that.
You mean simply:
std::unique_ptr<SDL_Surface, SurfaceDeleter> loadedSurface3{IMG_Load(path.c_str())};
is loadedSurface2 recommended over loadedSurface1 because it uses make_unique?
I can't see any benefit there. All you've achieved is to split your construction over two lines and lose the deleter.
make_unique and perfect forwarding
Herb Sutter, chair of the C++ standardization committee, writes on his blog:
That C++11 doesn’t include
make_unique
is partly an oversight, and it will almost certainly be added in the future.
He also gives an implementation that is identical with the one given by the OP.
Edit: std::make_unique
now is part of C++14.
C++ use of deleted function with unique_ptr, make_unique
In general, most of your errors originate from that std::unique_ptr
has no copy constructor. This is so that it can efficiently manage the scope of the pointer inside of it. One way around this is to create a new std::unique_ptr
, and copy all individual values over.
I've written an example class for you, perhaps it can help.
#include <memory>
template <class T>
class Matrix
{
private:
std::unique_ptr<T[]> data = nullptr;
size_t height, width;
public:
Matrix(size_t h, size_t w)
: height(h), width(w)
{
if(h*w == 0) return;
data = std::make_unique<T[]>(h*w);
}
Matrix(const Matrix& other)
{
height = other.height;
width = other.width;
data = std::make_unique<T[]>(height * width);
for(size_t i = 0; i < height; i++)
{
for(size_t j = 0; j < width; j++)
{
(*this)(j, i) = other(j,i);
}
}
}
Matrix operator=( const Matrix& other )
{
if(this == &other)
{
return *this;
}
height = other.height;
width = other.width;
data.reset(std::make_unique<T[]>(other.height * other.width));
for(size_t i = 0; i < height; i++)
{
for(size_t j = 0; j < width; j++)
{
(*this)(j, i) = other(j,i);
}
}
return *this;
}
T & operator()(size_t x, size_t y)
{
//If data is nullptr then this is undefined behaviour.
//Consider adding a throw or assert here
return data[y * height + x];
}
T operator()(size_t x, size_t y) const
{
//If data is nullptr then this is undefined behaviour.
//Consider adding a throw or assert here
return data[y * height + x];
}
size_t getHeight() const
{
return height;
}
size_t getWidth() const
{
return width;
}
};
As a final statement, if what you want to do is to create matrices for mathematical purposes, I suggest you give them static sizes for performance reasons. Adding in mathematical operators to a class like this involves additional logic for the cases where dimensions are mismatched. Statically sized matrices will solve this by themselves due to their typing. You can still do it like this, but be wary of any edge cases.
Related Topics
Order of Member Constructor and Destructor Calls
Alternative Virtual Function Calls Implementations
How to Code a Modulo (%) Operator in C/C++/Obj-C That Handles Negative Numbers
Why Is the C++ Initializer_List Behavior For Std::Vector and Std::Array Different
Ternary Operator : VS If...Else
Why Switch/Case and Not If/Else If
When Is a Private Constructor Not a Private Constructor
Generic Hash For Tuples in Unordered_Map/Unordered_Set
Destruction Order of Static Objects in C++
Why Is Template Argument Deduction Disabled With Std::Forward
String Literal Matches Bool Overload Instead of Std::String
How to Use Reference Parameters in C++
Calculating Normals in a Triangle Mesh