2011-04-18 61 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"); 
}; 

或者類似的設施。

相關問題