简体   繁体   中英

C++ Class template type std::list

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!

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;

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM