簡體   English   中英

為什么不能用大括號括起來的初始化程序列表構造隊列/堆棧? (C ++ 11)

[英]Why can't I construct a queue/stack with brace-enclosed initializer lists? (C++11)

程序1:

#include <iostream>
#include <cstdlib>
#include <vector>

int main(){

    //compiles successfully 
    std::vector<int> vec{1,2,3,4,5};

    return EXIT_SUCCESS;
}

程式2:

#include <iostream>
#include <cstdlib>
#include <queue>

int main(){

    //compiler error
    std::queue<int> que{1,2,3,4,5};

    return EXIT_SUCCESS;
}

錯誤信息:

main.cpp: In function ‘int main()’:
main.cpp:7:31: error: no matching function for call to ‘std::queue<int>::queue(<brace-enclosed initializer list>)’
main.cpp:7:31: note: candidates are:
/usr/include/c++/4.6/bits/stl_queue.h:141:7: note: std::queue<_Tp, _Sequence>::queue(_Sequence&&) [with _Tp = int, _Sequence = std::deque<int, std::allocator<int> >]
/usr/include/c++/4.6/bits/stl_queue.h:141:7: note:   candidate expects 1 argument, 5 provided
/usr/include/c++/4.6/bits/stl_queue.h:137:7: note: std::queue<_Tp, _Sequence>::queue(const _Sequence&) [with _Tp = int, _Sequence = std::deque<int, std::allocator<int> >]
/usr/include/c++/4.6/bits/stl_queue.h:137:7: note:   candidate expects 1 argument, 5 provided
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note: std::queue<int>::queue(const std::queue<int>&)
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note:   candidate expects 1 argument, 5 provided
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note: std::queue<int>::queue(std::queue<int>&&)
/usr/include/c++/4.6/bits/stl_queue.h:92:11: note:   candidate expects 1 argument, 5 provided

題:
為什么不能像矢量一樣初始化隊列?
我想它們不是序列容器,但是那為什么重要呢?
我敢肯定有充分的理由,但是我找不到任何解釋。

gcc(Ubuntu / Linaro 4.6.1-9ubuntu3)4.6.1

我不認為與容器適配器而不是容器無關(盡管我承認我不確定為什么要省略正確的構造函數)。

當將帶有括號的初始化器列表與std::vector ,您正在使用此(C ++ 11中的新增功能)構造函數:

vector(initializer_list<T>, const Allocator& = Allocator());

查看std::queue的定義,可用的構造函數為:

explicit queue(const Container&);
explicit queue(Container&& = Container());
template <class Alloc> explicit queue(const Alloc&);
template <class Alloc> queue(const Container&, const Alloc&);
template <class Alloc> queue(Container&&, const Alloc&);
template <class Alloc> queue(const queue&, const Alloc&);
template <class Alloc> queue(queue&&, const Alloc&);

顯然沒有構造函數接受初始化列表。

我非常確定,盡管是容器適配器,但如果需要的話,這樣的構造函數將是微不足道的。 例如:

#include <deque>
#include <initializer_list>
#include <iostream>

template <class T, class container=std::deque<T> >
class myqueue {
    container data;
public:
    explicit myqueue(std::initializer_list<T> t) : data(t) {}
    void pop() { data.pop_front(); }
    T front() const { return data.front(); }
    bool empty() const { return data.empty(); }
};

int main(){
    myqueue<int> data {1, 2, 3, 4};
    while (!data.empty()) {
        std::cout << data.front() << "\n";
        data.pop();
    }
    return 0;
}

g ++ 4.7毫無疑問地接受了這一點,並精確地產生了您期望的輸出:

1
2
3
4

盡管我還沒有與其他任何編譯器一起進行過測試,但是我看不出任何其他編譯器也無法與此配合的原因(當然,前提是它們必須實現必要的功能)。

編輯:我只是看了一些委員會文件,提議在C ++中增加initalizer_lists(例如N1890,N1919,N2100,N2215,N2220),在我看來,這就像一個簡單的疏忽。 早期的許多文章都是更具概念性的,但是N2220對該工作文件提出了大量建議的語言。 對於std::array (對於一個示例),它特別指出不需要更改。 然后,它遍歷dequevector[unordered_][multi_](set|map) ,並顯示每個元素所需的更改-但在任何方向上都沒有提及堆棧或隊列。 沒有建議添加對std::initializer_list支持,也沒有建議(如std::array )對其進行省略。

我得出的結論是,這是一個簡單的疏忽,可能由於以下兩個原因而被漏掉了:1)適配器幾乎是但不是完全是容器,以及2)適配器類似乎沒有被大量使用,因此忘記了關於他們的事情可能相當容易(當然,這也是普遍存在的第三個原因:大多數現任委員會成員都過度勞累)。

Edit2:我可能應該再添加一個細節:由於stackqueue都可以接受另一個容器進行初始化,因此您可以輕松地執行以下操作:

std::stack<int> data(std::vector<int>{1,2,3,4});

這有些冗長,但不太可能造成效率損失(容器將作為右值引用傳遞,因此其表示將被“竊取”,而不是被復制)。 但是有一個警告:如果您使用的容器類型與容器適配器下面的容器不匹配,您將獲得一個副本而不是一個移動(因此可能會降低效率)。

queue<int> q({1, 2, 3});

std::queuestd::stack實際上不是容器 ,它們被稱為使用容器的容器適配器 (默認為std::deque )。 因此,您不能將其初始化為其他容器。

編輯

為了使容器能夠使用初始化列表,它必須具有一個以std::initializer_list作為參數的構造函數。 容器適配器不這樣做。 如果是故意的,還是對標准委員會的監督取決於任何人的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM