Хранить шаблонный объект в контейнере - PullRequest
0 голосов
/ 18 октября 2010

Можно ли хранить шаблонный класс, такой как

template <typename rtn, typename arg>
class BufferAccessor {
  public:
    int ThreadID;
    virtual rtn do_work(arg) = 0;  
}; 

BufferAccessor<void,int> access1;
BufferAccessor<int,void> access2;

, в том же контейнере, как вектор или список

edit: Цель этого - попытаться сделать циркулярбуфер, в котором объекты, которые хотят использовать буфер, должны зарегистрироваться в буфере.Буфер будет сохранять boost :: shared_ptr для объектов доступа и генерировать обратный вызов для тех функций, которые будут выдвигать или извлекать данные в / из буфера.Обратный вызов будет использоваться в созданной мной общей рабочей функции потока, аналогичной пулу потоков с тем, что им необходим доступ к объекту общей памяти.Ниже приведен код, который я набрал, который может помочь проиллюстрировать то, что я пытаюсь сделать, но он еще не скомпилирован, и я также впервые использую 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
            }

Ответы [ 2 ]

3 голосов
/ 18 октября 2010

Нет, это не так, потому что контейнеры STL однородны, а access1 и access2 имеют совершенно разные несвязанные типы.Но вы можете сделать класс BufferAccessor не шаблонным, а рабочий элемент в качестве шаблона, например:

class BufferAccessor
{
   template<class R, class A>
   R doWork(A arg) {...}
};

В этом случае вы можете хранить BufferAccessors в контейнере, но вы не можете сделатьфункция шаблона члена виртуальная.

0 голосов
/ 18 октября 2010

Да, вы можете использовать vector<BufferAccessor<void,int> > для хранения BufferAccessor<void,int> объектов и vector<BufferAccessor<int,void> > для хранения BufferAccessor<int,void> объектов.

То, что вы не можете сделать, это использовать один и тот же вектор для хранения как BufferAccessor<int,void>, так и BufferAccessor<void,int> объект Причина, по которой он не работает, заключается в том, что BufferAccessor<void,int> и BufferAccessor<int,void> - это два разных класса

Note: можно использовать один и тот же вектор для хранения как BufferAccessor<int,void>, так и BufferAccessor<void,int>, ноВы должны будете хранить их как void *, используя shared_ptr<void>.Или еще лучше, вы можете использовать boost::variant

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...