Reputation: 1622
I came across below Queue template class,
template <class T>
class Queue {
protected:
// Data
std::queue<T> queue_;
typename std::queue<T>::size_type size_max_;
// Thread gubbins
std::mutex mutex_;
std::condition_variable full_;
std::condition_variable empty_;
// Exit
std::atomic_bool quit_{false};
std::atomic_bool finished_{false};
public:
Queue(const size_t size_max);
bool push(T &&data);
bool pop(T &data);
// The queue has finished accepting input
void finished();
// The queue will cannot be pushed or popped
void quit();
};
using intQueue = Queue<std::unique_ptr<int, std::function<void(int*)>>>
and i don't understand the use of std::function<void(int*)>
in above using statement. Why don't we write it as using intQueue = Queue<std::unique_ptr<int>>
instead.
Upvotes: 0
Views: 102
Reputation: 23629
There are actually 2 types of std::unique_ptr
:
Although it is still one class template, both types of unique_ptr
are not interchangeable. So a unique_ptr
defined like std::unique_ptr<int>
cannot be given a custom deleter, whereas std::unique_ptr<int, std::function<void(int*)>>
CAN be given a custom deleter.
This is unlike std::shared_ptr
, for which there is actually only 1 type (per pointee type of course). So you can have a type std::shared_ptr<Book>
and still give it a custom deleter.
The reason why this difference is made for std::unique_ptr
is to minimize memory consumption. In almost all cases the unique_ptr
will use the default deleter, and so storing one pointer instead of 2 (the second for the deleter) is sufficient. Only in those cases where the class template is instantiated with a deleter-template-argument, the type will store 2 pointers.
EDIT:
And of course, don't forget about Brian's remark below: the std::unique_ptr
without custom deleter is also more efficient since the call to the deleter is 'hard-coded' and thus can be inlined, without having the overhead of a virtual call to the custom deleter. This makes this std::unique_ptr
as efficient as calling delete yourself (without the risk of forgetting to call it).
Upvotes: 2
Reputation: 63117
std::function<void(int*)>
is an object that can hold any "void(int*) function"-like value. Notably you can change a std::function
object to hold different functions and function objects during it's lifetime.
It is used here as the (optional) Deleter
type parameter for std::unique_ptr
, which is used to retain knowledge of how to free the raw pointer held by the std::unique_ptr
.
Adding these things together allows int
s allocated by different means, requiring different deallocations, to be present in the same queue. This is a similar idea to the std::pmr
containers.
Upvotes: 0