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.
queue
constructorSection: 23.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:
23.6.3.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(i), and it also provides wording for 1196(i). ]
Change [ontainer.adaptor], p1:
The container adaptors each take a
Container
template parameter, and each constructor takes aContainer
reference argument. This container is copied into theContainer
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 aContainer
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 23.6.3.1 [queue.defn], [queue.cons]:
queue
constructors [queue.cons]explicit queue(const Container& cont);Effects: Initializes
c
withcont
.explicit queue(Container&& cont = Container());Effects: Initializes
c
withstd::move(cont)
.queue(queue&& q)Effects: Initializes
c
withstd::move(q.c)
.For each of the following constructors, if
uses_allocator<container_type, Alloc>::value
isfalse
, then the constructor shall not participate in overload resolution.template <class Alloc> explicit queue(const Alloc& a);Effects: Initializes
c
witha
.template <class Alloc> queue(const container_type& cont, const Alloc& a);Effects: Initializes
c
withcont
as the first argument anda
as the second argument.template <class Alloc> queue(container_type&& cont, const Alloc& a);Effects: Initializes
c
withstd::move(cont)
as the first argument anda
as the second argument.template <class Alloc> queue(queue&& q, const Alloc& a);Effects: Initializes
c
withstd::move(q.c)
as the first argument anda
as the second argument.queue& operator=(queue&& q);Effects: Assigns
c
withstd::move(q.c)
.Returns:
*this
.
Add to 23.6.4.2 [priqueue.cons]:
priority_queue(priority_queue&& q);Effects: Initializes
c
withstd::move(q.c)
and initializescomp
withstd::move(q.comp)
.For each of the following constructors, if
uses_allocator<container_type, Alloc>::value
isfalse
, then the constructor shall not participate in overload resolution.template <class Alloc> explicit priority_queue(const Alloc& a);Effects: Initializes
c
witha
and value-initializescomp
.template <class Alloc> priority_queue(const Compare& compare, const Alloc& a);Effects: Initializes
c
witha
and initializescomp
withcompare
.template <class Alloc> priority_queue(const Compare& compare, const Container& cont, const Alloc& a);Effects: Initializes
c
withcont
as the first argument anda
as the second argument, and initializescomp
withcompare
.template <class Alloc> priority_queue(const Compare& compare, Container&& cont, const Alloc& a);Effects: Initializes
c
withstd::move(cont)
as the first argument anda
as the second argument, and initializescomp
withcompare
.template <class Alloc> priority_queue(priority_queue&& q, const Alloc& a);Effects: Initializes
c
withstd::move(q.c)
as the first argument anda
as the second argument, and initializescomp
withstd::move(q.comp)
.priority_queue& operator=(priority_queue&& q);Effects: Assigns
c
withstd::move(q.c)
and assignscomp
withstd::move(q.comp)
.Returns:
*this
.
Change 23.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 23.6.6.2 [stack.defn], [stack.cons]:
stack
constructors [stack.cons]stack(stack&& s);Effects: Initializes
c
withstd::move(s.c)
.For each of the following constructors, if
uses_allocator<container_type, Alloc>::value
isfalse
, then the constructor shall not participate in overload resolution.template <class Alloc> explicit stack(const Alloc& a);Effects: Initializes
c
witha
.template <class Alloc> stack(const container_type& cont, const Alloc& a);Effects: Initializes
c
withcont
as the first argument anda
as the second argument.template <class Alloc> stack(container_type&& cont, const Alloc& a);Effects: Initializes
c
withstd::move(cont)
as the first argument anda
as the second argument.template <class Alloc> stack(stack&& s, const Alloc& a);Effects: Initializes
c
withstd::move(s.c)
as the first argument anda
as the second argument.stack& operator=(stack&& s);Effects: Assigns
c
withstd::move(s.c)
.Returns:
*this
.