std::unique_ptr takes as a type-parameter a type that is responsible for deleting the owned pointer. There is a default deleter that uses ::operator delete and looks something like:As per the quoted code - I guess I'm not sure what exactly is going on. You're making a structure that overloads the (), takes a texture, and then frees it? and then the last line - using TexturePtr. I'm not sure where TexturePtr is declared, or how it's defined, or what it is really. What is happening when you make a unique pointer with Texture and TextureDeleter?
struct default_deleter {
void operator()(void* ptr) const {
delete ptr;
}
};
The operator() is invoked when it's time to delete the pointer. This is called a "functor" in C++ vernacular. It's a type you can instantiate and then call operator() on as if it were a function, e.g.auto deleter = default_deleter();
deleter(pointer_to_delete);
// or the shorter version; first set of () invokes the constructor and
// creates a temporary instance, second set of () invoked operator() on that instance
defeault_deleter()(pointer_to_delete);
The definition of unique_ptr uses this type parameter as a functor, similar to how std::map uses std::less for its comparison operator. The definition looks something like:template <typename T, typename D = default_deleter> // use default_deleter unless user specifies another type
class unique_ptr : private D { // use inheritance to get the empty base-class optimization
T* _ptr = nullptr;
public:
unique_ptr() = default;
unique_ptr(T* ptr) { reset(ptr); }
~unique_ptr() { reset(nullptr); }
void reset(T* ptr) {
// note that the following is called even if _ptr is null; the deleter must
// deal with that, which default_deleter does since delete can be safely
// called on a null pointer; SDL_Free*() functions also typically are safe
// to call on a null pointer, too.
// release our currently owned pointer:
this->D::operator()(_ptr); }
// take ownership of the new pointer
_ptr = ptr;
}
// all the other member functions and operators too, of course
};
The use of a type with an overloaded operator() is common in the STL and C++. It's how you can provide a function with enclosed state as a type parameter. Recall that a C++ lambda is just a syntactical short-hand for making a structure like this, e.g.auto lambda = [](int a){ return a * 2; };
struct __lambda_magic_secret_name{ int operator()(int a){ return a * 2; }};
auto lamba = __lambda_magic_secret_name();
That's because the operator() is so crucial to how C++ higher-order functions can be written and composed.Unfortunately, since the lambda syntax creates an instance of the generated type rather than expanding to the type, it's a bit more difficult to use a lambda for a unique_ptr deleter. Rules about how lambdas can be used make it so we have to resort to a pre-C++11 functor object like _TextureDeleter.