为什么不能用大括号括起来的初始化器列表构造队列/堆栈? (C ++ 11) [英] Why can't I construct a queue/stack with brace-enclosed initializer lists? (C++11)

查看:69
本文介绍了为什么不能用大括号括起来的初始化器列表构造队列/堆栈? (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

问题:

为什么不能像矢量一样初始化队列? br>
我想它们不是顺序容器,但是为什么会这样呢?

我确定有充分的理由,但是我找不到任何解释。

Question:
why can't queues be initialized like vectors?
I suppose they aren't sequence containers, but why would that matter?
I'm sure there is a good reason, but I can't find any explanations.

gcc(Ubuntu / Linaro 4.6.1-9ubuntu3)4.6.1

gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1

推荐答案

我认为与容器适配器无关,而不是与容器适配器无关容器(尽管我承认我不确定为什么会省略正确的构造函数)。

I don't think it really has anything to do with being container adapters rather than containers (though I'll admit I'm uncertain exactly why the correct constructor is omitted).

当在 std中使用带括号的初始化列表时:: vector ,您正在使用此(C ++ 11中的新增功能)构造函数:

When you use a braced initializer list with std::vector, you're using this (new in C++11) constructor:

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

查看 std :: queue ,可用的构造函数为:

Looking at the definition of std::queue, the available constructors are:

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&);

带有初始化列表的构造函数显然不存在。

A constructor taking an initialization_list is conspicuously absent.

我非常确定,尽管是容器适配器,但如果需要的话,这样的构造函数将是微不足道的。例如:

I'm quite certain that despite being a container adapter, such a constructor would be trivial if it was desired. Just for example:

#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毫无疑问地接受了这一点,并产生了您想要的输出期望:

g++ 4.7 accepts this without any problems, and produces exactly the output you'd expect:

1
2
3
4

尽管我尚未与任何其他编译器进行过测试,但我看不出任何其他编译器也无法正常运行的原因(当然,前提是它们实现了必要的功能。)

Although I haven't tested with any other compilers, I can't see any reason other compilers wouldn't work fine with this as well (provided they implement the necessary features, of course).

编辑:我只是浏览了委员会的一些文件,提议在C ++中增加initalizer_lists(例如,N1890, N1919,N2100,N2215,N2220),在我看来,这就像一个简单的疏忽。早期的许多文章都是更具概念性的,但是N2220对该工作文件提出了大量建议的语言。对于 std :: array (例如),它特别指出不需要更改。然后,它通过 deque vector [unordered _] [multi _](set | map ),并显示每个内容所需的更改-但在任何方向上都没有提及堆栈或队列。没有提议增加对 std :: initializer_list 的支持,也没有建议(例如 std :: array )省略它们的理由。

I just did some looking through the committee papers proposing the addition of initalizer_lists to C++ (e.g., N1890, N1919, N2100, N2215, N2220) and it looks to me like a simple oversight. Many of the earlier papers are more conceptual, but N2220 has a fair amount of proposed language for the working paper. For std::array (for one example) it specifically points out that no change is needed. It then goes through deque, vector, [unordered_][multi_](set|map), and shows changes needed for each -- but no mention is made of stack or queue at all, in either direction. No proposal to add support for std::initializer_list, nor (like std::array) reasoning for their omission.

我得出的结论是这是一个简单的疏忽,可能由于以下两个原因而漏了:1)适配器几乎是但不是完全是容器,以及2)适配器类似乎并没有被大量使用,因此忘记它们可能很容易(当然,这是无处不在的第三个原因:大多数活跃的委员会成员都过度劳累)。

I'd conclude that it was a simple oversight, that probably slipped through for two reasons: 1) the adapters are almost, but not quite containers, and 2) the adapter classes don't seem to be used a whole lot, so forgetting about them was probably fairly easy (and, of course, the ever-pervasive third reason: most of the active committee members are horribly overworked).

Edit2:我可能应该再添加一个细节:由于 stack queue 都可以接受另一个容器进行初始化,则可以很容易地执行以下操作:

I should probably add one more detail: since stack and queue can both accept another container for the initialization, you can pretty easily do something like:

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

这有点冗长,但不太可能造成效率损失(容器将作为右值引用,因此其表示形式将被窃取,而不是被复制)。不过有一个警告:如果您使用的容器类型与容器适配器下面的容器不匹配,您将得到一个副本而不是一个举动(因此可能会失去一些效率)。

This is somewhat verbose, but unlikely to cause any loss of efficiency (the container will be passed as an rvalue reference, so its representation will be "stolen" instead of copied). There is one caveat though: if the type of container you use doesn't match the container underlying the container adapter, you'll get a copy rather than a move (and consequently, may lose some efficiency).

这篇关于为什么不能用大括号括起来的初始化器列表构造队列/堆栈? (C ++ 11)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆