pulling out unique_ptr from unique_ptr<T,Deleter> - c++

Can someone please advise on how to return the unique pointer from a templatised unique pointer pool with a custom deletor.
In the code snippet below i am using ObjectPool.h as my template class to get a stack of unique pointers .
I am using ObjectPool to create a sharedpool object in DBConnection.h and later in DBConnection.cpp i am simply returning the object to DBExec .
I get compile errors in DBConnection.cpp related to conversion of pointer with deleter to normal unique pointer.
> Class that will manage connection objects.
**DBConnectionPool.h**
#ifndef DBCONNECTIONPOOL_H
#define DBCONNECTIONPOOL_H
#include "DBExec.h"
#include "ObjectPool.h"
class DBConnectionPool {
static SharedPool<DBExec> pool;
static DBConnectionPool* instance;
DBConnectionPool& operator=(const DBConnectionPool&);
DBConnectionPool(const DBConnectionPool&);;
DBConnectionPool(){};
public:
...
**static std::unique_ptr<DBExec> getQueryObject();**
};
#endif /* DBCONNECTIONPOOL_H */
**DBConnection.cpp**
>implementation of getQueryObject
**std::unique_ptr<DBExec> DBConnectionPool::getQueryObject() {
return std::move(pool.acquire());
}**
/* Class that manages the unique pointer */
**ObjectPool.h**
#ifndef OBJECTPOOL_H
#define OBJECTPOOL_H
#include <memory>
#include <stack>
#include <mutex>
#include <assert.h>
template <class T>
class SharedPool {
/* Class that manages the unique pointer */
public:
using ptr_type = std::unique_ptr<T, std::function<void(T*)> >;
SharedPool() {
}
virtual ~SharedPool() {
}
void add(std::unique_ptr<T> t) {
std::lock_guard<std::mutex> lck (mt);
pool_.push(std::move(t));
}
ptr_type acquire() {
std::lock_guard<std::mutex> lck (mt);
assert(!pool_.empty());
ptr_type tmp(pool_.top().release(),
[this](T * ptr) {
this->add(std::unique_ptr<T>(ptr));
});
pool_.pop();
return std::move(tmp);
}
bool empty() const {
std::lock_guard<std::mutex> lck (mt);
return pool_.empty();
}
size_t size() const {
std::lock_guard<std::mutex> lck (mt);
return pool_.size();
}
std::stack<std::unique_ptr<T>>& getPoolStack () {
return pool_;
}
private:
> thread safe
std::mutex mt;
std::stack<std::unique_ptr<T> > pool_;
};
#endif /* OBJECTPOOL_H */

std::unique_ptr<T,D> and std::unique_ptr<T> are unrelated types (unless D=std::default_delete<T>). So you need to specify the type of the deleter in all your typedefs.
The next problem is you can't actually type out the type of your deleter, since it's a lambda type. So you may have to switch from a lambda to a named callable type.
template <class T>
class SharedPool {
public:
class Deleter {
public:
void operator()(T* ptr) const {
pool->add(std::unique_ptr<T,Deleter>(ptr));
}
private:
explicit Deleter(SharedPool* pool) : pool(pool) {}
SharedPool* pool;
friend class SharedPool<T>;
};
using ptr_type = std::unique_ptr<T, Deleter>;
You might also consider using std::shared_ptr since it type-erases its deleter type, but you don't seem to need the sharedness.

If I understand you correctly, you want to get a regular unique_ptr from one that has a custom deleter. This is not possible because returning a unique_ptr from another unique_ptr would violate the uniqueness of that pointer. Your only option would be to convert it to something, where the deleter is hidden from the type (i.e., type erasure).

It sounds like what you want is type erasure, or at least partial type erasure. A simple solution would be to just use std::shared_ptr:
std::shared_ptr<T>(new T, custom_deleter);
This would provide some overhead over std::unique_ptr, though some overhead is unavoidable.

Related

C++ storing different pointer types in one map (and handle the destroying)

In my server project I have a connection class which handles one connection to one client. In this connection class I want to store different datas for different systems which aren't defined in the connection class - because the outside should control completely what data is stored. So for example if I want to add a minigame I can just add the data for the minigame (like TMinigameData) to the connection and use it without change anything in the Connection just for this minigame.
My current approach is the following:
public:
template <typename T>
void clear_data()
{
auto it = _bind_data.find(typeid(T).hash_code());
if (it != _bind_data.end())
{
#ifdef _DEBUG
delete it->second.second;
#else
delete it->second;
#endif
_bind_data.erase(it);
}
}
template <typename T>
void bind_data(T*&& data)
{
bind_data(std::unique_ptr<T>(data));
}
template <typename T>
void bind_data(std::unique_ptr<T>&& data)
{
clear_data<T>();
#ifdef _DEBUG
_bind_data[typeid(T).hash_code()] = std::make_pair(sizeof(T), data.release());
#else
_bind_data[typeid(T).hash_code()] = data.release();
#endif
}
template <typename T>
T* get_data(bool create_if_not_exists = false)
{
auto it = _bind_data.find(typeid(T).hash_code());
if (it == _bind_data.end())
{
if (create_if_not_exists)
{
auto data_ptr = new T();
bind_data(std::unique_ptr<T>(data_ptr));
return data_ptr;
}
return nullptr;
}
#ifdef _DEBUG
assert(sizeof(T) == it->second.first, "Trying to get wrong data type from connection");
return (T*) it->second.second;
#else
return (T*) it->second;
#endif
}
private:
#ifdef _DEBUG
std::unordered_map<size_t, std::pair<size_t, void*>> _bind_data;
#else
std::unordered_map<size_t, void*> _bind_data;
#endif
The problem here is the destructor of the different datas won't be called because it's a void pointer. I know the type when adding it into my map but afterwards it gets lost. I don't know how I could store the type / destructor for the specific object.... is my approach generally wrong or what should I do?
Key to a working solution is either virtual inheritance or a custom deleter, as Rinat Veliakhmedov pointed out in his answer already.
However, you cannot use the virtual classes directly, as you'd suffer from object slicing or not being able to use arbitrary types within the same map.
So you need one level of indirection more. To be able to make the polymorphic approach working, you rely on further pointers to avoid object slicing, something like
std::unordered_map<size_t, std::pair<void*, std::unique_ptr<BaseDeleter>>>
std::unordered_map<size_t, std::unique_ptr<void*, std::unique_ptr<BaseDeleter>>>
In first case, you now need to implement all the correct deletion outside the map, second case doesn't work at all as a std::unique_ptr cannot serve as a custom deleter. In both cases, best you can do is wrapping the entire stuff in a separate class, e. g. the polymorphic approach:
class DataKeeper
{
struct Wrapper
{
virtual ~Wrapper() { }
};
template <typename T>
struct SpecificWrapper : Wrapper
{
SpecificWrapper(T* t) : pointer(t) { }
std::unique_ptr<T> pointer;
};
std::unique_ptr<Wrapper> data;
public:
DataKeeper()
{ }
template <typename T>
DataKeeper(T* t)
: data(new SpecificWrapper<T>(t))
{ }
template <typename T>
DataKeeper(std::unique_ptr<T>&& t)
: DataKeeper(t.release())
{ }
};
Now we have an easy to use class DataKeeper that hides all the polymorphism stuff away. I personally consider the custom deleter approach even neater; for that, we'll profit from the fact that ordinary functions can be used as custom deleters as well:
class DataKeeper
{
template <typename T>
static void doDelete(void* t)
{
delete static_cast<T*>(t);
}
std::unique_ptr<void, void(*)(void*)> pointer;
// ^ function pointer type
public:
DataKeeper()
: pointer(nullptr, nullptr)
{}
template <typename T>
DataKeeper(T* t)
: pointer(t, &DataKeeper::doDelete<T>)
// ^ instantiate appropriate template function and pass
// as custom deleter to smart pointer constructor
{ }
template <typename T>
DataKeeper(std::unique_ptr<T>&& t)
: DataKeeper(t.release())
{ }
};
You could now try e. g. as follows:
std::unordered_map<size_t, DataKeeper> map;
map[1] = DataKeeper(new int(7));
map.insert(std::pair<size_t, DataKeeper>(2, std::make_unique<double>(10.12)));
map.emplace(3, std::make_unique<std::string>("aconcagua"));
Create a class with some output in the destructor and you'll see that it gets called correctly.

factory, unique_ptr and static_cast

Consider polymorphic classes with a base object, a derived interface, and a final object:
// base object
struct object
{
virtual ~object() = default;
};
// interfaces derived from base object
struct interface1 : object
{
virtual void print_hello() const = 0;
template<typename T>
static void on_destruction(object* /*ptr*/)
{
std::cout << "interface1::on_destruction" << std::endl;
}
};
// final object
struct derived1 : interface1
{
virtual void print_hello() const override
{
std::cout << "hello" << std::endl;
}
static std::string get_type_name()
{
return "derived1";
}
};
In the real use case, final objects are defined through a plugin system, but that is not the point. Note that I want to be able to call on_destruction when an object is destroyed (see register_object below). I want to use these classes as follows:
int main()
{
// register derived1 as an instantiable object,
// may be called in a plugin
register_object<derived1>();
// create an instance using the factory system
auto instance = create_unique<interface1>("derived1");
instance->print_hello();
return 0;
}
Using std::unique_ptr to manage the objects, I ended up with the following code for register_object:
template<typename T>
using unique = std::unique_ptr<
T,
std::function<void(object*)> // object deleter
>;
namespace
{
std::map< std::string, std::function<unique<object>(void)> > factory_map;
}
template<typename T>
void register_object()
{
factory_map.emplace(
T::get_type_name(),
[]()
{
unique<T> instance{
new T,
[](object* ptr)
{
T::on_destruction<T>(ptr);
delete ptr;
}
};
return static_move_cast<object>(
std::move(instance)
);
}
);
}
And the create* functions:
unique<object> create_unique_object(const std::string& type_name)
{
auto f = factory_map.at(type_name);
return f();
}
template<typename T>
unique<T> create_unique(const std::string& type_name)
{
return static_move_cast<T>(
create_unique_object(type_name)
);
}
You noticed in register_object and create_unique the call to static_move_cast, which is declared as:
template<typename U, typename T, typename D>
std::unique_ptr<U, D>
static_move_cast
(
std::unique_ptr<T, D>&& to_move_cast
)
{
auto deleter = to_move_cast.get_deleter();
return std::unique_ptr<U, D>{
static_cast<U*>(
to_move_cast.release()
),
deleter
};
}
The goal behind static_move_cast is to allow static_cast on std::unique_ptr while moving the deleter during the cast. The code is working, but I feel like hacking std::unique_ptr. Is there a way to refactor the code to avoid my static_move_cast?
static_move_cast is unnecessary within register_object, since you can just use the converting constructor of unique_ptr template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ):
unique<T> instance{
new T,
// ...
};
return instance;
Or, even simpler, construct and return a unique<object> directly, since T* is convertible to object*:
return unique<object>{
new T,
// ...
};
However for create_unique the use of static_move_cast is unavoidable, since the converting constructor of unique_ptr won't work for downcasts.
Note that shared_ptr has static_pointer_cast, which performs downcasts, but there is no corresponding facility for unique_ptr, presumably because it it is considered straightforward and correct to perform the cast yourself.
I would say it is good solution given the requirements. You transfer the responsibility to the caller of create_unique. He must give correct combination of type and string and string that is in the registry.
auto instance = create_unique<interface1>("derived1");
// ^^^^^^^^^^ ^^^^^^^^
// what if those two don't match?
You could improve it a bit by changing the static_cast to dynamic_cast. And the caller of create_unique should always check that he got non-null pointer before calling anything on it.
Or at least use dynamic_cast with assert in debug mode, so you catch mismatches while developing.
Alternative refactoring: Have separate factory for every existing interface.

Submitting a task to a Thread Pool Implementation Issue

I'm using thread pools for the first time, working out of Anthony Williams' Concurrency In Action book. He provides a basic thread pool class that I'm trying to use but not an implementation - just the class. The issue is that I'm new to templates and thread-pools. This is probably a simple question/answer but I can't figure it out. I have this function to submit jobs to the pool:
class SimpleThreadPool
{
public:
...
// -- Submit a task to the thread pool
template <typename FunctionType>
void submit(FunctionType f);
...
};
I'm trying to call it but honestly don't know how (have tried a few different things):
boost::interprocess::scoped_lock<std::mutex> lock(m_mtx_map);
for(const auto& elem : m_logger_map)
{
m_thread_pool->submit< std::function< void > >(elem.second->operator());
}
Here the m_thread_pool is a pointer to the thread pool and the map contains (string,pointer) pairs where the pointer points to a logging object which has it's main run/processing method in operator().
I'm getting a:
error: no matching function call 'SimpleThreadPool::submit(< unresolved overloaded function type >)'
How do I correctly use this submit function?
Thank you!
UPDATE -----
Here's the implementation in the thread pool class:
// -- Submit Method
/** void submit(FunctionType f)
* #desc : Submit a job (function pointer) to the pool
*/
template <typename FunctionType> void SimpleThreadPool::submit(FunctionType f)
{
m_q_work.push(std::function<void()>(f));
}
m_q_work is a thread-safe Queue.
// -- Launch a new worker thread
/** void m_worker_thread()
* #desc : Worker thread main method for getting tasks and executing
*/
void SimpleThreadPool::m_worker_thread()
{
while(!m_done)
{
std::function<void()> task;
if(m_q_work.try_pop(task))
{
task();
}
else
{
std::this_thread::yield();
}
}
}
I'm guessing I probably need to change the implementation based on my comment to the response below.
The following compiled in g++
#include <map>
#include <string>
#include <functional>
class SimpleThreadPool {
public:
template <typename FunctionType>
void submit(FunctionType f) { }
};
class Logger {
public:
void operator()() { }
};
int main(int argc,char **argv) {
std::map<std::string,Logger*> m_logger_map;
m_logger_map["one"]=new Logger();
SimpleThreadPool *m_thread_pool=new SimpleThreadPool();
for (const auto& elem: m_logger_map) {
m_thread_pool->submit<std::function< void() > >(*elem.second);
}
}
Changes are:
1.- std::function< void() >, instead of std::function<void> (yours only had the return type, but not the parameters (note that I've defined the operator() with empty parameters).
2.- *elem.second as the argument to submit (instead of elem.second->operator()). Note that a function object (i.e. an object of class with an operator() defined) can be used as a std::function (refer to the examples in the std::function reference)
Edit: avoid the lack of copy constructor
Instead of using directly the Logger object that cannot be copy-constructed, we can use a Wrapper object. This Wrapper object contains a reference to the Logger class.
I've also changed the code to use shared_ptr, because memory ownership becomes more complex:
#include <map>
#include <string>
#include <functional>
#include <memory>
class SimpleThreadPool {
public:
template <typename FunctionType>
void submit(FunctionType f) { }
};
class Logger {
public:
Logger() { }
Logger(const Logger&) = delete; // Logger cannot be copied
void operator()() { }
};
template <typename T>
class Wrapper {
public:
Wrapper(const std::shared_ptr<T> &l):mWrapped(l) { } // Wraps a T reference
void operator()() {
(*mWrapped)(); // expected to be a function object
}
private:
std::shared_ptr<T> mWrapped;
};
int main(int argc,char **argv) {
// Need to change the definition of the map
// to contain shared_ptr.
std::map<std::string,std::shared_ptr<Logger> > m_logger_map;
m_logger_map["one"]=std::make_shared<Logger>();
SimpleThreadPool *m_thread_pool=new SimpleThreadPool();
for (const auto& elem: m_logger_map) {
// Create the Wrapper object from the reference we've
// obtained from the map.... The wrapper can be copied
// around, but the reference will not change.
std::function<void()> f=Wrapper<Logger>(elem.second);
m_thread_pool->submit<std::function< void() > >(f);
}
}

Locking a shared_ptr

I have an shared object that need to be send to a system API and extract it back later. The system API receives void * only. I cannot use shared_ptr::get() because it do not increases the reference count and it could be released by other threads before extract from the system API. Sending a newed shared_ptr * will work but involves additional heap allocation.
One way to do it is to let the object derived from enable_shared_from_this. However, because this class template owns only a weak_ptr, it is not enough to keep the object from released.
So my solution looks like the following:
class MyClass:public enable_shared_from_this<MyClass> {
private:
shared_ptr<MyClass> m_this;
public:
void *lock(){
m_this=shared_from_this();
return this;
}
static shared_ptr<MyClass> unlock(void *p){
auto pthis = static_cast<MyClass *>(p);
return move(pthis->m_this);
}
/* ... */
}
/* ... */
autp pobj = make_shared<MyObject>(...);
/* ... */
system_api_send_obj(pobj->lock());
/* ... */
auto punlocked = MyClass::unlock(system_api_reveive_obj());
Are there any easier way to do this?
The downside of this solution:
it requires an additional shared_ptr<MyClass> in the MyClass object layout, in addition of a weak_ptr in the base class enable_shared_from_this.
As I mentioned in the comments, access to lock() and unlock() concurrently is NOT Safe.
The worst thing is that this solution can only support lock() once before a call of unlock(). If the same object is to be use for multiple system API calls, additional reference counting must be implemented.
If we have another enable_lockable_shared_from_this class it will be greate:
class MyClass:public enable_lockable_shared_from_this<MyClass> {
/* ... */
}
/* ... */
autp pobj = make_shared<MyObject>(...);
/* ... */
system_api_send_obj(pobj.lock());
/* ... */
auto punlocked = unlock_shared<MyClass>(system_api_reveive_obj());
And the implementation of enable_lockable_shared_from_this is similar as enable_shared_from_this, the only difference is it implements lock() and a helper function unlock_shared. The calling of those functions only explicitly increase and decrease use_count(). This will be the ideal solution because:
It eliminate the additional space cost
It reuses the facilities existing for shared_ptr to guarantee concurrency safety.
The best thing of this solution is that it supports multiple lock() calls seamlessly.
However, the only biggest downside is: it is not available at the moment!
UPDATE:
At least two answers to this question involves a container of pointers. Please compare those solutions with the following:
class MyClass:public enable_shared_from_this<MyClass> {
private:
shared_ptr<MyClass> m_this;
mutex this_lock; //not necessory for single threading environment
int lock_count;
public:
void *lock(){
lock_guard lck(this_lock); //not necessory for single threading environment
if(!lock_count==0)
m_this=shared_from_this();
return this;
}
static shared_ptr<MyClass> unlock(void *p){
lock_guard lck(this_lock); //not necessory for single threading environment
auto pthis = static_cast<MyClass *>(p);
if(--lock_count>0)
return pthis->m_this;
else {
lock_count=0;
return move(pthis->m_this); //returns nullptr if not previously locked
}
}
/* ... */
}
/* ... */
autp pobj = make_shared<MyObject>(...);
/* ... */
system_api_send_obj(pobj->lock());
/* ... */
auto punlocked = MyClass::unlock(system_api_reveive_obj());
This is absolutely an O(1) vs O(n) (space; time is O(log(n)) or similar, but absolutely greater than O(1) ) game.
I am now have an idea of the following:
template<typename T>
struct locker_helper{
typedef shared_ptr<T> p_t;
typedef typename aligned_storage<sizeof(p_t), alignment_of<p_t>::value>::type s_t;
};
template<typename T> void lock_shared(const shared_ptr<T> &p){
typename locker_helper<T>::s_t value;
new (&value)shared_ptr<T>(p);
}
template<typename T> void unlock_shared(const shared_ptr<T> &p){
typename locker_helper<T>::s_t value
= *reinterpret_cast<const typename locker_helper<T>::s_t *const>(&p);
reinterpret_cast<shared_ptr<T> *>(&value)->~shared_ptr<T>();
}
template<typename T>
void print_use_count(string s, const shared_ptr<T> &p){
cout<<s<<p.use_count()<<endl;
}
int main(int argc, char **argv){
auto pi = make_shared<int>(10);
auto s = "pi use_count()=";
print_use_count(s, pi); //pi use_count()=1
lock_shared(pi);
print_use_count(s, pi);//pi use_count()=2
unlock_shared(pi);
print_use_count(s, pi);//pi use_count()=1
}
and then we can implement the original example as following:
class MyClass:public enable_shared_from_this { /*...*/ };
/* ... */
auto pobj = make_shared<MyClass>(...);
/* ... */
lock_shared(pobj);
system_api_send_obj(pobj.get());
/* ... */
auto preceived =
static_cast<MyClass *>(system_api_reveive_obj())->shared_from_this();
unlock_shared(preceived);
It is easy to implement a enable_lockable_shared_from_this with this idea. However, the above is more generic, allows control things that is not derived from enable_lockable_from_this` template class.
By adjusting the previous answer, I finally get the following solution:
//A wrapper class allowing you to control the object lifetime
//explicitly.
//
template<typename T> class life_manager{
public:
//Prevent polymorphic types for object slicing issue.
//To use with polymorphic class, you need to create
//a container type for storage, and then use that type.
static_assert(!std::is_polymorphic<T>::value,
"Use on polymorphic types is prohibited.");
//Example for support of single variable constructor
//Can be extented to support any number of parameters
//by using varidict template.
template<typename V> static void ReConstruct(const T &p, V &&v){
new (const_cast<T *>(&p))T(std::forward<V>(v));
}
static void RawCopy(T &target, const T &source){
*internal_cast(&target) = *internal_cast(&source);
}
private:
//The standard said that reterinterpret_cast<T *>(p) is the same as
//static_cast<T *>(static_cast<void *>(p)) only when T has standard layout.
//
//Unfortunately shared_ptr do not.
static struct { char _unnamed[sizeof(T)]; } *internal_cast(const T *p){
typedef decltype(internal_cast(nullptr)) raw;
return static_cast<raw>(static_cast<void *>(const_cast<T *>(p)));
}
};
//Construct a new instance of shared_ptr will increase the reference
//count. The original pointer was overridden, so its destructor will
//not run, which keeps the increased reference count after the call.
template<typename T> void lock_shared(const std::shared_ptr<T> &p){
life_manager<shared_ptr<T> >::ReConstruct(p, std::shared_ptr<T>(p));
}
//RawCopy do bit-by-bit copying, bypassing the copy constructor
//so the reference count will not increase. This function copies
//the shared_ptr to a temporary, and so it will be destructed and
//have the reference count decreased after the call.
template<typename T> void unlock_shared(const std::shared_ptr<T> &p){
life_manager<shared_ptr<T> >::RawCopy(std::shared_ptr<T>(), p);
}
This is actually the same as my previous version, however. The only thing I did is to create a more generic solution to control object lifetime explicitly.
According to the standard(5.2.9.13), the static_cast sequence is definitely well defined. Furthermore, the "raw" copy behavior could be undefined but we are explicitly requesting to do so, so the user MUST check the system compatibility before using this facility.
Furthermore, actually only the RawCopy() are required in this example. The introduce of ReConstruct is just for general purpose.
Why not just wrap the void * API in something that tracks the lifetime of that API's references to your object?
eg.
typedef std::shared_ptr<MyClass> MyPtr;
class APIWrapper
{
// could have multiple references to the same thing?
// use multiset instead!
// are references local to transient messages processed in FIFO order?
// use a queue! ... etc. etc.
std::set<MyPtr, SuitableComparator> references_;
public:
void send(MyPtr const &ref)
{
references_.insert(ref);
system_api_send_obj(ref.get());
}
MyPtr receive(void *api)
{
MyPtr ref( static_cast<MyClass *>(api)->shared_from_this() );
references_.erase(ref);
return ref;
}
};
Obviously (hopefully) you know the actual ownership semantics of your API, so the above is just a broad guess.
How about using the following global functions that use pointers-to-smart-pointers.
template<typename T> void *shared_lock(std::shared_ptr<T> &sp)
{
return new std::shared_ptr<T>(sp);
}
template<typename T> std::shared_ptr<T> shared_unlock(void *vp)
{
std::shared_ptr<T> *psp = static_cast<std::shared_ptr<T,D>*>(sp);
std::shared_ptr<T> res(*psp);
delete psp;
return res;
}
You have an extra new/delete but the original type is unmodified. And additionally, concurrency is not an issue, because each call to shared_lock will return a different shared_ptr.
To avoid the new/delete calls you could use an object pool, but I think that it is not worth the effort.
UPDATE:
If you are not going to use multiple threads in this matter, what about the following?
template<typename T> struct SharedLocker
{
std::vector< std::shared_ptr<T> > m_ptrs;
unsigned lock(std::shared_ptr<T> &sp)
{
for (unsigned i = 0; i < m_ptrs.size(); ++i)
{
if (!m_ptrs[i])
{
m_ptrs[i] = sp;
return i;
}
}
m_ptrs.push_back(sp);
return m_ptrs.size() - 1;
}
std::shared_ptr<T> unlock(unsigned i)
{
return std::move(m_ptrs[i]);
}
};
I've changed the void* into an unsigned, but that shouldn't be a problem. You could also use intptr_t, if needed.
Assuming that most of the time there will be only a handful of objects in the vector, maybe even no more than 1, the memory allocations will only happen once, on first insertion. And the rest of the time it will be at zero cost.

How do I create a container that will work properly with std::unique_ptr as a template parameter?

Suppose I have a Mutexed queue called MQueue:
#include <deque>
template< typename T >
class MQueue
{
public:
T* pop()
{
lock();
T* ptr = nullptr;
// get it out of m_dq...
unlock();
return ptr;
}
// push, etc... and other methods
private:
std::deque<T*> m_dq;
};
The following instantiation has been tested and works fine:
MQueue< int > my_simple_mq;
What kinds of modifications do I need to make to MQueue to ensure that
MQueue< std::unique_ptr< int > > my_smart_mq;
will behave properly? I have attempted to browse the code to std::vector<> for reference, but it's difficult for me to discern which parts of the implementation are pertinent for the proper working of smart pointers. Any references or links would be greatly appreciated.
If you just want to replace the T* with unique_ptr<T>, then it would look something like:
template< typename T >
class MQueue
{
public:
std::unique_ptr<T> pop()
{
lock();
std::unique_ptr<T> ptr = std::move(m_dq.back());
m_dq.pop_back();
unlock();
return ptr;
}
// push, etc... and other methods
private:
std::deque<std::unique_ptr<T>> m_dq;
};
But on reading your comment in the question, it is now not clear that is what you're asking. If you want your unqiue_ptr to sometimes own the pointer and sometimes not, you can write a custom deleter which holds a flag stating whether or not it should delete the pointer. Clients of unique_ptr can access a reference to the deleter (via the get_deleter() accessor) to inspect/change that flag.
Here's example (untested) code that shows how that might look:
template <class T>
class my_deleter
{
bool owns_;
public:
explicit my_deleter(bool owns) : owns_(owns) {}
bool owns() const {return owns_;}
void set_owns(bool owns) {owns_ = owns;}
void operator()(T* p) {if (owns_) delete p;}
};
template< typename T >
class MQueue
{
public:
typedef std::unique_ptr<T, my_deleter<T>> Ptr;
Ptr pop()
{
lock();
Ptr ptr = std::move(m_dq.back());
m_dq.pop_back();
unlock();
return ptr;
}
// push, etc... and other methods
private:
std::deque<Ptr> m_dq;
};