C++ 类模板类型 std::list

Posted

技术标签:

【中文标题】C++ 类模板类型 std::list【英文标题】:C++ Class template type std::list 【发布时间】:2017-09-12 16:54:07 【问题描述】:

我有一个像下面这样的线程安全队列类,

类 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_;
;

现在,我希望这个队列包含列表。所以,我使用如下:

ClassB.h:

template<typename std::list<Message*>>
class CmdQ;

CmdQ<std::list<Message*>>* msgListQ_;

但是,我不断收到以下错误:

错误 1 ​​错误 C2993: 'std::list<_ty>' : 非类型的非法类型 模板参数'__formal'

错误 3 错误 C2975:“CmdQ”:模板参数无效 '未命名参数',预期的编译时常量表达式

我参考了一些文档,模板类型不能接受std::list,但会接受指向列表的指针,因此也尝试在 ClassB.h 中使用指向列表的指针,如下所示:

template<typename std::list<Message*>*>
class CmdQ;

CmdQ<std::list<Message*>*>* msgListQ_; 

但我仍然面临错误。

感谢任何帮助。

谢谢!

【问题讨论】:

不应该std::queue queue_;std::queue&lt;Q&gt; queue_; 无论如何您都不需要显式实例化。你可以只使用模板来声明你的变量。 @NathanOliver std::queue&lt;Q*&gt; queue,而不是 template&lt;typename std::list&lt;Message*&gt;&gt; class CmdQ; 是来自外太空的语法。为什么你认为你需要这条线? 【参考方案1】:

我想错误的部分是typename in

template<typename std::list<Message*>*>
class CmdQ;

试试

template <std::list<Message*>*>
class CmdQ;

或避免它并简单地写

CmdQ<std::list<Message*>*>* msgListQ_; 

不管怎样

我参考了一些模板类型不能接受 std::list 的文档

什么?

一个模板类

template <typename>
class foo  ;

不接受std::list不带参数传递,如下

foo<std::list>  fl0;

(因为std::list,在这种方式下,是一个模板-模板参数)但是用参数接受它

foo<std::list<int>> fl1;

【讨论】:

感谢您的建议。我改为“模板<:list>*> class CmdQ;”如前所述,然后使用“CmdQ<:list>*>* msgListQ_;”。但是,我仍然看到与上面提到的相同的错误 1 ​​和错误 3。对此有何其他见解? @MonicaRajasekaran - 你有没有尝试删除它并简单地写CmdQ&lt;std::list&lt;Message*&gt;*&gt;* msgListQ_;?无论如何,问题可能在于标题包含问题。您是否包含(之前)实现CmdQ 的标头?您是否包含标准标题list?我认为您应该准备一个最小但完整的示例来重现错误。 是的!那行得通。万分感谢。那个类的前向声明把我搞砸了。【参考方案2】:

由于无效,类被破坏(无法编译)

 std::queue queue_;

声明。 std::queue 是一个模板,您需要提供一个有效的模板参数。

由于您推送和弹出Q* 类型的东西,与模板其余部分一致的唯一声明将是

 std::queue<Q*> queue_;

现在CmdQ&lt;std::list&lt;Message*&gt;*&gt; 完全错误,因为内部队列将存储堆分配的指向指针的指针列表(存储指针本身)。你当然不希望这样。

但是,将队列类限制为使用指针(并拥有指向的对象)是一个糟糕的设计。如此严格地限制选择是没有意义的。不建议将原始 C 样式指针用于一般用途,应首选智能指针。移动指针也没什么意义。拥有一个列表也没有什么意义,而不是它的元素。如果您从类中删除所有星号,并删除对delete 的调用,则模板会变得更简单、更通用且更一致。然后你可以使用

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

或您喜欢的任何组合。您可能需要在这里和那里添加几个对std::move 的调用。您可能还想添加一个可选的元素删除器,以防有人出于某种莫名其妙的原因想要将您的模板与原始指针一起使用。

【讨论】:

以上是关于C++ 类模板类型 std::list的主要内容,如果未能解决你的问题,请参考以下文章

std::list 模板在其实例类型中是不是需要复制构造函数(或等效项)?

C++学习34 模板类

STL源码学习std::list类的类型别名分析

派生类的模板类作为函数的参数 - 危险?

C++多态模板类,模板类型对象的实例化

[C++模板] --- 类模板