Store Templated Object in Container
Is it possible to store a templated class like
template <typename rtn, typename arg>
class BufferAccessor {
public:
int ThreadID;
virtual rtn do_work(arg) = 0;
};
BufferAccessor<void,int> access1;
BufferAccessor<int,void> access2;
in the same container like a vec开发者_JAVA技巧tor or list
edit: The purpose for this is I am trying to make a circular buffer where the objects that want to use the buffer need to register with the buffer. The buffer will store a boost::shared_ptr to the accessor objects and generate a callback to there functions that will push or pull data to/from the buffer. The callback will be used in a generic thread worker function that I have created similar to a thread pool with the fact that they need to access a shared memory object. Below is some code I have typed up that might help illustrate what I am trying to do, but it hasn't been compiled it yet and this is also my first time using bind, function, multi-threading
typedef boost::function<BUF_QObj (void)> CallbackT_pro;
typedef boost::function<void (BUF_QObj)> CallbackT_con;
typedef boost::shared_ptr<BufferAccessor> buf_ptr;
// Register the worker object
int register_consumer(BufferAccesser &accessor) {
mRegCons[mNumConsumers] = buf_ptr(accessor);
return ++mNumConsumers;
}
int register_producer(BufferAccesser &accessor) {
mRegPros[mNumProducers] = buf_ptr(accessor);
return ++mNumProducers;
}
// Dispatch consumer threads
for(;x<mNumConsumers; ++x) {
CallBack_Tcon callback_con = boost::bind(&BufferAccessor::do_work, mRegCons[x]);
tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::consumerWorker, this, callback_con));
consumers.add(tw);
}
// Dispatch producer threads
for(x=0;x<mNumProducers; ++x) {
CallBack_Tpro callback_pro = boost::bind(&BufferAccessor::do_work, mRegPros[x], _1);
tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::producerWorker, this, callback_pro));
producers.add(tw);
}
// Thread Template Workers - Consumer
void consumerWorker(CallbackT_con worker) {
struct BUF_QObj *qData;
while(!mRun)
cond.wait(mLock);
while(!mTerminate) {
// Set interruption point so that thread can be interrupted
boost::thread::interruption_point();
{ // Code Block
boost::mutex::scoped_lock lock(mLock);
if(buf.empty()) {
cond.wait(mLock)
qData = mBuf.front();
mBuf.pop_front(); // remove the front element
} // End Code Block
worker(qData); // Process data
// Sleep that thread for 1 uSec
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
} // End of while loop
}
// Thread Template Workers - Producer
void producerWorker(CallbackT_pro worker) {
struct BUF_QObj *qData;
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
while(!mRun)
cond.wait(mLock);
while(!mTerminate) {
// Set interruption point so that thread can be interrupted
boost::thread::interruption_point();
qData = worker(); // get data to be processed
{ // Code Block
boost::mutex::scoped_lock lock(mLock);
buf.push_back(qData);
cond.notify_one(mLock);
} // End Code Block
// Sleep that thread for 1 uSec
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
} // End of while loop
}
No it's not, because STL containers are homogenous, and access1 and access2 have completely different unrelated types. But you could make the class BufferAccessor non-template one but the do-work member as a template, like this:
class BufferAccessor
{
template<class R, class A>
R doWork(A arg) {...}
};
In this case you could store BufferAccessors in a container, but you can't make a member template function virtual.
Yes, you can use vector<BufferAccessor<void,int> >
to store BufferAccessor<void,int>
objects and vector<BufferAccessor<int,void> >
to store BufferAccessor<int,void>
objects.
What you cant do is use same vector to store both BufferAccessor<int,void>
and BufferAccessor<void,int>
object
The reason it doesnt work is because BufferAccessor<void,int>
, and BufferAccessor<int,void>
are two different classes
Note
: it is possible to use same vector to store both BufferAccessor<int,void>
and BufferAccessor<void,int>
but you would have to either store them as void *
using shared_ptr<void>
. Or better yet you can use a boost::variant
精彩评论