I have a boost::ptr_map
which stores abstract base class (e.g. VectorWrapperBase) as values and this allows me to map strings to vectors of different types.
boost::ptr_map<std::string, VectorWrapperBase> memory_map;
//...
memory_map.insert(str_key, new VectorWrapper<T>());
This appears to work. However, when I have memory_map
as a member of another class and attempt to store that class in an std::map
, compilation fails.
class AgentMemory {
//...
private:
boost::ptr_map<std::string, VectorWrapperBase> memory_map;
};
std::map<std::string, AgentMemory> agent_map;
//...
agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory()));
The last line fails with:
/SOMEPATH/boost_1_48_0/boost/ptr_container/clone_allocator.hpp:34
error: cannot allocate an object of abstract type ‘xyz::VectorWrapperBase’
Being new to C++, this is baffling.
I suspect that error is down to the map insertion copying the AgentMemory
object which involves cloning the ptr_map
. And since my VectorWrapper
objects are not cloneable, the error is raised.
My questions are:
- Why am I getting the error? (Are my suspicions even close to what's actually happening?)
- How do I address this?
To address the compilation error, I've considered the following, but without much experience with C++ can't decide which is more appropriate:
- Remove the pure specifier (
= 0
) soVectorWrapperBase
is no longer abstract- This feels like a hack since
VectorWrapperBase
should never be instantiated
- This feels like a hack since
- Make the VectorWrappers cloneable
- This seems to work, but in my use case only empty containers are assigned to the top-level map so VectorWrappers within the inner
ptr_map
need never be cloned. The cloneability would therefore be there just to appease the compiler and does not reflect the actual usage.
- This seems to work, but in my use case only empty containers are assigned to the top-level map so VectorWrappers within the inner
- Forget
ptr_map
and use astd::map
andshared_ptr
instead.- I'm less keen on this solution as I would like the lifetime of the vector wrappers to be linked to that of the map. I'm also a little concerned (perhaps unnecessarily so?) about the potential overheads of extensive use of
shared_ptr
in a heavily multi-threaded application.
- I'm less keen on this solution as I would like the lifetime of the vector wrappers to be linked to that of the map. I'm also a little concerned (perhaps unnecessarily so?) about the potential overheads of extensive use of