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.
Section: 24.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:
24.6.6.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 24.6.6.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 24.6.7.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 24.6.8.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 24.6.8.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.