为什么std::queue允许冗余类型规范

Why std::queue allows redundant type specification?

本文关键字:冗余 类型 std queue 许冗余 为什么      更新时间:2023-10-16

STL库类std::queue的前向声明如下:

namespace std {
    template<typename T, class container = deque<T>> class queue
}

这意味着我们可以声明一个具有不同类型规范的queue类型对象,像这样:

std::queue<float, std::deque<std::string>> string_queue;

为什么会这样?像这样声明队列不是更类型安全吗?

template<class implementation>
class queue_base
{
private:
    implementation m_impl;
    /* ----------------------------------------------------------- */
public:
    typedef implementation                      container_type;
    typedef typename implementation::size_type  size_type;
    typedef queue_base<implementation>          this_type;
    typedef typename implementation::value_type value_type;
    /* ----------------------------------------------------------- */
    queue_base         ();
    queue_base         (queue_base const& other);
    explicit queue_base(container_type const& other);
    /* ----------------------------------------------------------- */
    value_type&       back ();
    value_type const& back () const;
    bool              empty() const;
    value_type&       front();
    value_type const& front() const;
    void              pop  ();
    void              push (value_type const& value);
    size_type         size () const;
    /* ----------------------------------------------------------- */
}; /* template<class> class queue_base */
/* --------------------------------------------------------------- */
我所见过的std::queue的大多数实现都以与上面代码中相同的方式实现了'value_type'和'size_type'。因此,模板形参'T'只用于模板形参'container' (std::deque)的默认形参。

我的意思是,我不认为这是"好",在上面的声明例子中浮点规范被忽略;

像这样声明队列不是更类型安全吗?

更类型安全,是的,但不那么方便。queue的普通用户并不关心底层容器,它实际上只是一个实现细节。它们只关心元素类型。这也是为了与其他容器类保持一致。

如果queue类可以通过为容器指定一个类模板来使用就更好了,如下所示:

std::queue<int, std::list> myqueue;

从逻辑上讲,人们可能会期望这样的内容:

template<typename T, template<typenameU> class C = std::deque>
class queue
{
protected:
    C<T> c;
public:
    //  ...
};

问题是std::deque不会匹配模板参数,因为它实际上是:

template<typename T, typename Allocator = allocator<T> >
class deque ...

额外的template参数阻止它工作。如果的第二个参数中添加了额外的参数queue,则大多数用户定义容器不能使用;因为他们不会有第二个参数。当前的解决方案避免了这个问题(同时仍然允许客户端。代码来实例化std::queue<float>,例如,没有(担心底层容器类型)

最后,为什么不呢?您的std::queue<float, std::deque<std::string> >示例可能无法编译,但是像std::queue<bool, std::vector<char> >这样的东西是错误的(避免有问题的std::vector<bool>)?只要…这两种方式都有隐含的转换,这取决于客户端以确保它能按他的意愿运作。(当然,实际上,这几乎不是个问题,因为客户机代码很少出现这种情况指定容器

如果您只关心防止"愚蠢"的情况,一个简单的完整性检查就足够了:

template <typename T, typename Container>
class queue
{
  static_assert(std::is_same<T, typename Container::value_type>::value,
    "queue require T and Container::value_type to be identical");
};

或c++ 03中的类似功能