2011-04-18 37 views
4

STL库类的std ::队列的向前声明如下:为什么std :: queue允许冗余类型规范?

namespace std { 
    template<typename T, class container = deque<T>> class 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 */ 
/* --------------------------------------------------------------- */ 

性病的大多数实现::队列我见过实施同样的方式,你可以在看“VALUE_TYPE”和“SIZE_TYPE”我上面的代码。因此,模板参数'T'仅用于模板参数'container'(std :: deque)的默认参数。

我的意思是,我不认为上面的声明示例中的float规范被忽略是“很好”的;不管它是否有效。

+0

请参阅[此答案](http://stackoverflow.com/questions/4962518/templates-and-stl/4962708#4962708)以及。 – GManNickG 2011-04-18 10:32:08

回答

2

那岂不是更类型安全申报队列是这样的:

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

更妙的是,如果queue类是通过指定的容器类模板使用,如下:

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

但有不幸的是用C这样做++的没有好,可移植的方法。

+0

嗯,我认为这是一个弱点。当我使用std :: list而不是std :: deque作为std :: queue的容器时,我还需要完整地输入std :: queue >。 – 0xbadf00d 2011-04-18 10:20:00

+1

@Sascha但你*不*,通常使用'std :: list'。队列的正常使用情况是使用默认值,即'std ::队列'。这不是一个真正的弱点,针对常见情况进行优化是一个很好的设计原则。 – 2011-04-18 10:21:42

+0

是的,我知道你的意思,但在我看来,你不应该优先考虑优化(任何类型)而不是完整性。 – 0xbadf00d 2011-04-18 10:26:44

0

逻辑上,人们可能会想到是这样的:

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 ... 

额外的模板争论阻止它工作。如果 额外的参数被添加到第二个参数 queue,那么大多数用户定义的容器不能被使用,因为他们没有第二个参数。目前的 解决方案避开了这个问题(虽然仍然允许客户端 实例化std::queue<float>,例如,没有 担心潜在的容器类型)。

而最后,为什么不呢?你的std::queue<float, std::deque<std::string> >的例子可能不会编译,但是什么 错误,像std::queue<bool, std::vector<char> > (避免有问题的std::vector<bool>)?只要 有一个隐式转换两种方式,它是由客户端 确保它做他想做的。 (实际上,当然, 这几乎从来不是问题,因为客户端代码 很少指定容器。)

+0

就像我上面说过的:在大多数实现中,第一个模板参数被忽略。所以,'bool'在你的例子中没有意义。 – 0xbadf00d 2011-04-18 10:35:35

+0

所以我明白了。事实上,这是标准所要求的。尽管如此,我觉得这很奇怪。我会期待完全相反的。 (或者某种静态断言这两种类型是相同的。) – 2011-04-18 11:15:33

1

如果你只关心防止“傻”的情况下,一个简单的完整性检查就足够了:在C++ 03

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"); 
}; 

或者类似的设施。

相关问题