Reputation: 70
I have a thread safe queue class like below,
Class CmdQ:
template <typename Q>
class CmdQ
{
public:
CmdQ() :
queue_(),
queueMutex_(){};
~CmdQ() {
while (!queue_.empty()) {
Q* element(std::move(this->queue_.front()));
this->queue_.pop();
delete element;
}
};
void push(Q* commands) {
std::unique_lock<std::mutex> lock(this->queueMutex_);
queue_.push(commands);
this->mutexCondition_.notify_all();
}
void pop() {
std::unique_lock<std::mutex> lock(this->queueMutex_);
while(this->queue_.empty())this->mutexCondition_.wait(lock);
Q* element(std::move(this->queue_.front()));
this->queue_.pop();
delete element;
}
Q* front() {
std::unique_lock<std::mutex> lock(this->queueMutex_);
while(this->queue_.empty())this->mutexCondition_.wait(lock); if (!queue_.empty()) {
return (queue_.front());
}
return NULL;
}
bool empty() {
std::unique_lock<std::mutex> lock(this->queueMutex_);
return queue_.empty();
}
void clear() {
std::unique_lock<std::mutex> lock(this->queueMutex_);
while (!queue_.empty()) {
Q* element(std::move(this->queue_.front()));
this->queue_.pop();
delete element;
}
}
unsigned int size() {
std::unique_lock<std::mutex> lock(this->queueMutex_);
return queue_.size();
}
private:
std::queue queue_;
std::mutex queueMutex_;
std::condition_variable mutexCondition_;
};
Now, I want this queue to contain lists. And so, I used as below:
ClassB.h:
template<typename std::list<Message*>>
class CmdQ;
CmdQ<std::list<Message*>>* msgListQ_;
But, I keep getting the errors such as:
Error 1 error C2993: 'std::list<_Ty>' : illegal type for non-type template parameter '__formal'
Error 3 error C2975: 'CmdQ' : invalid template argument for 'unnamed-parameter', expected compile-time constant expression
I referred to some documentation that template type cannot accept std::list
but will accept pointer to lists and so also tried using pointer to list like below in ClassB.h:
template<typename std::list<Message*>*>
class CmdQ;
CmdQ<std::list<Message*>*>* msgListQ_;
But I still keep facing errors.
Any help is appreciated.
Thanks!
Upvotes: 0
Views: 2054
Reputation: 119847
The class is broken (doesn't compile) because of the invalid
std::queue queue_;
declaration. std::queue
is a template and you need to supply a valid template argument.
Since you push and pop things of type Q*
, the only declaration consistent with the rest of the template would be
std::queue<Q*> queue_;
Now CmdQ<std::list<Message*>*>
is totally wrong as the internal queue would store heap-allocated pointers to pointers of lists (that store pointers themselves). You certainly don't want that.
It's a bad design to constrain your queue class to work with pointers (and to own the pointed object) though. It makes little sense to limit the choice so severely. Raw C-style pointers are not recommended for general use, smart pointers should be preferred. It also makes little sense to move pointers. It also makes little sense to own a list, bit not its elements. If you remove all asterisks from the class, and also remove the call to delete
, the template becomes simpler, more generic, and more consistent. You can then use
CmdQ<std::list<Message>> // store lists by value
CmdQ<std::list<Message*>*> // store pointers to lists of pointers (not recommended)
CmdQ<std::unique_ptr<std::list<std::shared_ptr<Message>>>> // etc
or any combination you like. You will probably have to add a couple of calls to std::move
here and there. You may also want to add an optional element deleter, just in case someone would want for some inexplicable reason to use your template with raw pointers.
Upvotes: 2
Reputation: 66190
I suppose the wrong part is the typename
in
template<typename std::list<Message*>*>
class CmdQ;
try with
template <std::list<Message*>*>
class CmdQ;
or avoid it and simply write
CmdQ<std::list<Message*>*>* msgListQ_;
Anyway
I referred to some documentation that template type cannot accept std::list
What?
a template class
template <typename>
class foo { };
doesn't accept std::list
if you pass it without argument, as follows
foo<std::list> fl0;
(because std::list
, in this way, is a template-template argument) but accept it with arguments
foo<std::list<int>> fl1;
Upvotes: 2