28

プログラム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

4

3 に答える 3

34
queue<int> q({1, 2, 3});
于 2014-12-14T05:50:38.037 に答える
33

コンテナーではなくコンテナーアダプターであることとは実際には何の関係もないと思います(ただし、正しいコンストラクターが省略されている理由は正確にはわかりません)。

でブレースされた初期化子リストを使用する場合は 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&);

initialize_listを取得するコンストラクターが著しく存在しません。

コンテナーアダプターであるにもかかわらず、そのようなコンストラクターは、必要に応じて簡単なものになると確信しています。ちょうど例:

#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特に変更が必要ないことを指摘しています。次に、、、を通過し、dequeそれぞれに必要な変更を示しますが、どちらの方向でも、スタックまたはキューについてはまったく言及されていません。それらの省略のサポートを追加する提案も、(のように)理由もありません。vector[unordered_][multi_](set|map)std::initializer_liststd::array

これは単純な見落としだったと思います。おそらく2つの理由で抜け落ちました。1)アダプタはほとんどコンテナですが、完全ではありません。2)アダプタクラスはあまり使用されていないようです。そのため、忘れてしまいます。それらについてはおそらくかなり簡単でした(そしてもちろん、これまでになく普及している3番目の理由:アクティブな委員会のメンバーのほとんどはひどく過労です)。

Edit2:おそらくもう1つ詳細を追加する必要がstackありqueueます。両方とも初期化のために別のコンテナーを受け入れることができるため、次のようなことを非常に簡単に行うことができます。

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

これはやや冗長ですが、効率が低下する可能性はほとんどありません(コンテナは右辺値参照として渡されるため、その表現はコピーされるのではなく「盗まれる」ことになります)。ただし、注意点が1つあります。使用するコンテナーのタイプが、コンテナーアダプターの下にあるコンテナーと一致しない場合、移動ではなくコピーを取得します(その結果、効率が低下する可能性があります)。

于 2012-04-24T07:48:58.237 に答える
10

std::queuestd::stack実際にはコンテナではなく、コンテナを使用するいわゆるコンテナアダプタです(デフォルトではstd::deque)。したがって、他のコンテナとして初期化することはできません。

編集

コンテナーが初期化子リストを使用できるようにするには、std::initializer_list引数としてasをとるコンストラクターが必要です。コンテナアダプタはそれを行いません。それが意図的であるか、標準化委員会の監視であるかどうかは、誰の解釈次第です。

于 2012-04-24T07:14:04.350 に答える