This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 1194. Unintended `queue` constructor

Section: 22.6 [container.adaptors] Status: C++11 Submitter: Howard Hinnant Opened: 2009-08-20 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [container.adaptors].

View all issues with C++11 status.

Discussion:

22.6.4.1 [queue.defn] has the following `queue` constructor:

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

This will be implemented like so:

>     template <class Alloc> explicit queue(const Alloc& a) : c(a) {}

The issue is that `Alloc` can be anything that a container will construct from, for example an `int`. Is this intended to compile?

>     queue<int> q(5);

Before the addition of this constructor, `queue<int>(5)` would not compile. I ask, not because this crashes, but because it is new and appears to be unintended. We do not want to be in a position of accidently introducing this "feature" in C++0X and later attempting to remove it.

I've picked on `queue`. `priority_queue` and `stack` have the same issue. Is it useful to create a `priority_queue` of 5 identical elements?

[ Daniel, Howard and Pablo collaborated on the proposed wording. ]

[ 2009-10 Santa Cruz: ]

> Move to Ready.

Proposed resolution:

[ This resolution includes a semi-editorial clean up, giving definitions to members which in some cases weren't defined since C++98. This resolution also offers editorially different wording for 976, and it also provides wording for 1196. ]

Change [ontainer.adaptor], p1:

> The container adaptors each take a `Container` template parameter, and each constructor takes a `Container` reference argument. This container is copied into the `Container` member of each adaptor. If the container takes an allocator, then a compatible allocator may be passed in to the adaptor's constructor. Otherwise, normal copy or move construction is used for the container argument. [Note: it is not necessary for an implementation to distinguish between the one-argument constructor that takes a `Container` and the one- argument constructor that takes an allocator_type. Both forms use their argument to construct an instance of the container. — end note]

Change [ueue.def], p1:

>     template <class T, class Container = deque<T> >
>     class queue {
>     public:
>       typedef typename Container::value_type      value_type;
>       typedef typename Container::reference       reference;
>       typedef typename Container::const_reference const_reference;
>       typedef typename Container::size_type       size_type;
>       typedef Container                           container_type;
>     protected:
>       Container c;

>     public:
>       explicit queue(const Container&);
>       explicit queue(Container&& = Container());
>       queue(queue&& q); : c(std::move(q.c)) {}
>       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(queue&&, const Alloc&);
>       queue& operator=(queue&& q); { c = std::move(q.c); return *this; }

>       bool empty() const          { return c.empty(); }
>       ...
>     };

Add a new section after 22.6.4.1 [queue.defn], [queue.cons]:

> `queue` constructors [queue.cons]

>     explicit queue(const Container& cont);

> > Effects: Initializes `c` with `cont`.

>     explicit queue(Container&& cont = Container());

> > Effects: Initializes `c` with `std::move(cont)`.

>     queue(queue&& q)

> > Effects: Initializes `c` with `std::move(q.c)`.

> For each of the following constructors, if `uses_allocator<container_type, Alloc>::value` is `false`, then the constructor shall not participate in overload resolution.

>     template <class Alloc>
>       explicit queue(const Alloc& a);

> > Effects: Initializes `c` with `a`.

>     template <class Alloc>
>       queue(const container_type& cont, const Alloc& a);

> > Effects: Initializes `c` with `cont` as the first argument and `a` as the second argument.

>     template <class Alloc>
>       queue(container_type&& cont, const Alloc& a);

> > Effects: Initializes `c` with `std::move(cont)` as the first argument and `a` as the second argument.

>     template <class Alloc>
>       queue(queue&& q, const Alloc& a);

> > Effects: Initializes `c` with `std::move(q.c)` as the first argument and `a` as the second argument.

>     queue& operator=(queue&& q);

> > Effects: Assigns `c` with `std::move(q.c)`.

> > Returns: `*this`.

Add to 22.6.5.2 [priqueue.cons]:

>     priority_queue(priority_queue&& q);

> > Effects: Initializes `c` with `std::move(q.c)` and initializes `comp` with `std::move(q.comp)`.

> For each of the following constructors, if `uses_allocator<container_type, Alloc>::value` is `false`, then the constructor shall not participate in overload resolution.

>     template <class Alloc>
>       explicit priority_queue(const Alloc& a);

> > Effects: Initializes `c` with `a` and value-initializes `comp`.

>     template <class Alloc>
>       priority_queue(const Compare& compare, const Alloc& a);

> > Effects: Initializes `c` with `a` and initializes `comp` with `compare`.

>     template <class Alloc>
>       priority_queue(const Compare& compare, const Container& cont, const Alloc& a);

> > Effects: Initializes `c` with `cont` as the first argument and `a` as the second argument, and initializes `comp` with `compare`.

>     template <class Alloc>
>       priority_queue(const Compare& compare, Container&& cont, const Alloc& a);

> > Effects: Initializes `c` with `std::move(cont)` as the first argument and `a` as the second argument, and initializes `comp` with `compare`.

>     template <class Alloc>
>       priority_queue(priority_queue&& q, const Alloc& a);

> > Effects: Initializes `c` with `std::move(q.c)` as the first argument and `a` as the second argument, and initializes `comp` with `std::move(q.comp)`.

>     priority_queue& operator=(priority_queue&& q);

> > Effects: Assigns `c` with `std::move(q.c)` and assigns `comp` with `std::move(q.comp)`.

> > Returns: `*this`.

Change 22.6.6.2 [stack.defn]:

>     template <class T, class Container = deque<T> >
>     class stack {
>     public:
>       typedef typename Container::value_type      value_type;
>       typedef typename Container::reference       reference;
>       typedef typename Container::const_reference const_reference;
>       typedef typename Container::size_type       size_type;
>       typedef Container                           container_type;
>     protected:
>       Container c;

>     public:
>       explicit stack(const Container&);
>       explicit stack(Container&& = Container());
>       stack(stack&& s);
>       template <class Alloc> explicit stack(const Alloc&);
>       template <class Alloc> stack(const Container&, const Alloc&);
>       template <class Alloc> stack(Container&&, const Alloc&);
>       template <class Alloc> stack(stack&&, const Alloc&);
>       stack& operator=(stack&& s);

>       bool empty() const          { return c.empty(); }
>       ...
>     };

Add a new section after 22.6.6.2 [stack.defn], [stack.cons]:

> `stack` constructors [stack.cons]

>     stack(stack&& s);

> > Effects: Initializes `c` with `std::move(s.c)`.

> For each of the following constructors, if `uses_allocator<container_type, Alloc>::value` is `false`, then the constructor shall not participate in overload resolution.

>     template <class Alloc>
>       explicit stack(const Alloc& a);

> > Effects: Initializes `c` with `a`.

>     template <class Alloc>
>       stack(const container_type& cont, const Alloc& a);

> > Effects: Initializes `c` with `cont` as the first argument and `a` as the second argument.

>     template <class Alloc>
>       stack(container_type&& cont, const Alloc& a);

> > Effects: Initializes `c` with `std::move(cont)` as the first argument and `a` as the second argument.

>     template <class Alloc>
>       stack(stack&& s, const Alloc& a);

> > Effects: Initializes `c` with `std::move(s.c)` as the first argument and `a` as the second argument.

>     stack& operator=(stack&& s);

> > Effects: Assigns `c` with `std::move(s.c)`.

> > Returns: `*this`.