The standard says that the container adaptors have a constructor with
a default argument, which serves as a default constructor. That
involves default-constructing the underlying sequence as the default
argument and then move-constructing the member variable from that
argument. Because std::deque allocates memory in its move constructor
this means the default constructor of an adaptor using std::deque
will allocate twice, which is wasteful and expensive.

This change adds a separate default constructor, defined as defaulted
(and adding default member-initializers to ensure the member variables
get value-initialized). This avoids the move-construction, so we only
allocate once when using std::deque.

As noted in Bugzilla this makes the default constructors non-explicit,
which is a change in behaviour, and not strictly conforming. I'm doing
that intentionally, because having default construction be explicit
for these types is stupid anyway.

Because the default constructor is defined as defaulted it will be
deleted when the underlying sequence isn't default constructible, so
we can still explicitly instantiate the adaptors in such cases (which
I've added tests for).

I'm also shuffling some tests around. Currently we have two explicit
instantiation tests for each adaptor, 1.cc and 1_c++0x.cc, which
originally tested it for C++98 and C++11. But since the default became
gnu++14 we now test twice in C++14 mode. So I'm replacing 1_c++0x.cc
with 1_c++98.cc which has { dg-options "-std=gnu++98.cc" } to force
testing that dialect.

        PR libstdc++/77528
        * include/bits/stl_queue.h (queue::c): Add default member initializer.
        (queue::queue()): Add constructor and define as defaulted.
        (queue::queue(_Sequence&&)): Remove default argument.
        (priority_queue::c, priority_queue::comp): Add default member
        initializers.
        (priority_queue::priority_queue()): Add constructor and define as
        defaulted.
        (priority_queue::priority_queue(const _Compare&, _Sequence&&)):
        Remove default argument for first parameter.
        * include/bits/stl_stack.h (stack::c): Add default member initializer.
        (stack::stack()): Add constructor and define as defaulted.
        (stack::stack(const _Sequence&)): Remove default argument.
        * testsuite/23_containers/priority_queue/requirements/
        explicit_instantiation/1.cc: Test explicit instantiation with
        non-DefaultConstructible sequence.
        * testsuite/23_containers/priority_queue/77528.cc: New test.
        * testsuite/23_containers/priority_queue/requirements/
        explicit_instantiation/1_c++0x.cc: Replace with 1_c++98.cc.
        * testsuite/23_containers/queue/77528.cc: New test.
        * testsuite/23_containers/queue/requirements/explicit_instantiation/
        1.cc: Test explicit instantiation with non-DefaultConstructible
        sequence.
        * testsuite/23_containers/queue/requirements/explicit_instantiation/
        1_c++0x.cc: Replace with 1_c++98.cc.
        * testsuite/23_containers/stack/77528.cc: New test.
        * testsuite/23_containers/stack/requirements/explicit_instantiation/
        1.cc: Test explicit instantiation with non-DefaultConstructible
        sequence.
        * testsuite/23_containers/stack/requirements/explicit_instantiation/
        1_c++0x.cc: Replace with 1_c++98.cc.

Tested powerpc64le-linux, committed to trunk.

We might want to backport this to the branches, but I'll let it bake
on trunk for a bit first.

commit 5fe45739d39c67fae0f9a3179c2f61b6c95428e4
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Thu Sep 8 14:32:37 2016 +0100

    PR77528 add default constructors for container adaptors
    
        PR libstdc++/77528
        * include/bits/stl_queue.h (queue::c): Add default member initializer.
        (queue::queue()): Add constructor and define as defaulted.
        (queue::queue(_Sequence&&)): Remove default argument.
        (priority_queue::c, priority_queue::comp): Add default member
        initializers.
        (priority_queue::priority_queue()): Add constructor and define as
        defaulted.
        (priority_queue::priority_queue(const _Compare&, _Sequence&&)):
        Remove default argument for first parameter.
        * include/bits/stl_stack.h (stack::c): Add default member initializer.
        (stack::stack()): Add constructor and define as defaulted.
        (stack::stack(const _Sequence&)): Remove default argument.
        * testsuite/23_containers/priority_queue/requirements/
        explicit_instantiation/1.cc: Test explicit instantiation with
        non-DefaultConstructible sequence.
        * testsuite/23_containers/priority_queue/77528.cc: New test.
        * testsuite/23_containers/priority_queue/requirements/
        explicit_instantiation/1_c++0x.cc: Replace with 1_c++98.cc.
        * testsuite/23_containers/queue/77528.cc: New test.
        * testsuite/23_containers/queue/requirements/explicit_instantiation/
        1.cc: Test explicit instantiation with non-DefaultConstructible
        sequence.
        * testsuite/23_containers/queue/requirements/explicit_instantiation/
        1_c++0x.cc: Replace with 1_c++98.cc.
        * testsuite/23_containers/stack/77528.cc: New test.
        * testsuite/23_containers/stack/requirements/explicit_instantiation/
        1.cc: Test explicit instantiation with non-DefaultConstructible
        sequence.
        * testsuite/23_containers/stack/requirements/explicit_instantiation/
        1_c++0x.cc: Replace with 1_c++98.cc.

diff --git a/libstdc++-v3/include/bits/stl_queue.h 
b/libstdc++-v3/include/bits/stl_queue.h
index 45eba09..6417b30 100644
--- a/libstdc++-v3/include/bits/stl_queue.h
+++ b/libstdc++-v3/include/bits/stl_queue.h
@@ -124,15 +124,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef          _Sequence                            container_type;
 
     protected:
-      /**
-       *  'c' is the underlying container.  Maintainers wondering why
-       *  this isn't uglified as per style guidelines should note that
-       *  this name is specified in the standard, [23.2.3.1].  (Why?
-       *  Presumably for the same reason that it's protected instead
+      /*  Maintainers wondering why this isn't uglified as per style
+       *  guidelines should note that this name is specified in the standard,
+       *  C++98 [23.2.3.1].
+       *  (Why? Presumably for the same reason that it's protected instead
        *  of private: to allow derivation.  But none of the other
        *  containers allow for derivation.  Odd.)
        */
+      /// @c c is the underlying container.
+#if __cplusplus >= 201103L
+      _Sequence c{};
+#else
       _Sequence c;
+#endif
 
     public:
       /**
@@ -143,12 +147,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       queue(const _Sequence& __c = _Sequence())
       : c(__c) { }
 #else
+      queue() = default;
+
       explicit
       queue(const _Sequence& __c)
       : c(__c) { }
 
       explicit
-      queue(_Sequence&& __c = _Sequence())
+      queue(_Sequence&& __c)
       : c(std::move(__c)) { }
 
       template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
@@ -440,8 +446,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     protected:
       //  See queue::c for notes on these names.
-      _Sequence  c;
+#if __cplusplus >= 201103L
+      _Sequence c{};
+      _Compare   comp{};
+#else
+      _Sequence c;
       _Compare   comp;
+#endif
 
     public:
       /**
@@ -454,6 +465,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : c(__s), comp(__x)
       { std::make_heap(c.begin(), c.end(), comp); }
 #else
+      priority_queue() = default;
+
       explicit
       priority_queue(const _Compare& __x,
                     const _Sequence& __s)
@@ -461,7 +474,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { std::make_heap(c.begin(), c.end(), comp); }
 
       explicit
-      priority_queue(const _Compare& __x = _Compare(),
+      priority_queue(const _Compare& __x,
                     _Sequence&& __s = _Sequence())
       : c(std::move(__s)), comp(__x)
       { std::make_heap(c.begin(), c.end(), comp); }
diff --git a/libstdc++-v3/include/bits/stl_stack.h 
b/libstdc++-v3/include/bits/stl_stack.h
index f7020ba..a0f9ee5 100644
--- a/libstdc++-v3/include/bits/stl_stack.h
+++ b/libstdc++-v3/include/bits/stl_stack.h
@@ -129,7 +129,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     protected:
       //  See queue::c for notes on this name.
+#if __cplusplus >= 201103L
+      _Sequence c{};
+#else
       _Sequence c;
+#endif
 
     public:
       // XXX removed old def ctor, added def arg to this one to match 14882
@@ -141,12 +145,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       stack(const _Sequence& __c = _Sequence())
       : c(__c) { }
 #else
+      stack() = default;
+
       explicit
       stack(const _Sequence& __c)
       : c(__c) { }
 
       explicit
-      stack(_Sequence&& __c = _Sequence())
+      stack(_Sequence&& __c)
       : c(std::move(__c)) { }
 
       template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/77528.cc 
b/libstdc++-v3/testsuite/23_containers/priority_queue/77528.cc
new file mode 100644
index 0000000..0f953bc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/priority_queue/77528.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <queue>
+
+struct NoCopying : std::vector<int>
+{
+  NoCopying() = default;
+  NoCopying(const NoCopying& x) : std::vector<int>(x)
+  { throw std::bad_alloc(); }
+};
+
+void
+test01()
+{
+  std::priority_queue<int, NoCopying> q;
+}
+
+int
+main()
+{
+  test01();
+}
diff --git 
a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
 
b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
index 7795547..77cade0 100644
--- 
a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1.cc
@@ -23,3 +23,11 @@
 #include <queue>
 
 template class std::priority_queue<int>;
+
+struct NonDefaultConstructible : std::vector<int> {
+  NonDefaultConstructible(int) { }
+};
+struct Cmp : std::less<int> {
+  Cmp(int) { }
+};
+template class std::priority_queue<int, NonDefaultConstructible>;
diff --git 
a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++0x.cc
 
b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++0x.cc
deleted file mode 100644
index b4af733..0000000
--- 
a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++0x.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// { dg-do compile { target c++11 } }
-
-// Copyright (C) 2009-2017 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this library; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-// This file tests explicit instantiation of library containers.
-
-#include <queue>
-
-template class std::priority_queue<int>;
diff --git 
a/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc
 
b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc
new file mode 100644
index 0000000..0b5b287
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/explicit_instantiation/1_c++98.cc
@@ -0,0 +1,33 @@
+// { dg-options "-std=gnu++98" }
+// { dg-do compile }
+
+// Copyright (C) 2009-2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// This file tests explicit instantiation of library containers.
+
+#include <queue>
+
+template class std::priority_queue<int>;
+
+struct NonDefaultConstructible : std::vector<int> {
+  NonDefaultConstructible(int) { }
+};
+struct Cmp : std::less<int> {
+  Cmp(int) { }
+};
+template class std::priority_queue<int, NonDefaultConstructible, Cmp>;
diff --git a/libstdc++-v3/testsuite/23_containers/queue/77528.cc 
b/libstdc++-v3/testsuite/23_containers/queue/77528.cc
new file mode 100644
index 0000000..dff6d6d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/queue/77528.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <queue>
+
+struct NoCopying : std::deque<int>
+{
+  NoCopying() = default;
+  NoCopying(const NoCopying& x) : std::deque<int>(x)
+  { throw std::bad_alloc(); }
+};
+
+void
+test01()
+{
+  std::queue<int, NoCopying> q;
+}
+
+int
+main()
+{
+  test01();
+}
diff --git 
a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
 
b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
index 7e49dae..5037365 100644
--- 
a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1.cc
@@ -23,3 +23,8 @@
 #include <queue>
 
 template class std::queue<int>;
+
+struct NonDefaultConstructible : std::deque<int> {
+  NonDefaultConstructible(int) { }
+};
+template class std::queue<int, NonDefaultConstructible>;
diff --git 
a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++0x.cc
 
b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++0x.cc
deleted file mode 100644
index 71a9003..0000000
--- 
a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++0x.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// { dg-do compile { target c++11 } }
-
-// Copyright (C) 2009-2017 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this library; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-// This file tests explicit instantiation of library containers.
-
-#include <queue>
-
-template class std::queue<int>;
diff --git 
a/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc
 
b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc
new file mode 100644
index 0000000..4590220
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/23_containers/queue/requirements/explicit_instantiation/1_c++98.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++98" }
+// { dg-do compile }
+
+// Copyright (C) 2009-2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// This file tests explicit instantiation of library containers.
+
+#include <queue>
+
+template class std::queue<int>;
+
+struct NonDefaultConstructible : std::deque<int> {
+  NonDefaultConstructible(int) { }
+};
+template class std::queue<int, NonDefaultConstructible>;
diff --git a/libstdc++-v3/testsuite/23_containers/stack/77528.cc 
b/libstdc++-v3/testsuite/23_containers/stack/77528.cc
new file mode 100644
index 0000000..dfc3a2a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/stack/77528.cc
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <stack>
+
+struct NoCopying : std::deque<int>
+{
+  NoCopying() = default;
+  NoCopying(const NoCopying& x) : std::deque<int>(x)
+  { throw std::bad_alloc(); }
+};
+
+void
+test01()
+{
+  std::stack<int, NoCopying> s;
+}
+
+int
+main()
+{
+  test01();
+}
diff --git 
a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
 
b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
index fe90364..b93286d 100644
--- 
a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1.cc
@@ -23,3 +23,8 @@
 #include <stack>
 
 template class std::stack<int>;
+
+struct NonDefaultConstructible : std::deque<int> {
+  NonDefaultConstructible(int) { }
+};
+template class std::stack<int, NonDefaultConstructible>;
diff --git 
a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++0x.cc
 
b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++0x.cc
deleted file mode 100644
index 033f02f..0000000
--- 
a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++0x.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// { dg-do compile { target c++11 } }
-
-// Copyright (C) 2009-2017 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library.  This library is free
-// software; you can redistribute it and/or modify it under the
-// terms of the GNU General Public License as published by the
-// Free Software Foundation; either version 3, or (at your option)
-// any later version.
-
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this library; see the file COPYING3.  If not see
-// <http://www.gnu.org/licenses/>.
-
-// This file tests explicit instantiation of library containers.
-
-#include <stack>
-
-template class std::stack<int>;
diff --git 
a/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc
 
b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc
new file mode 100644
index 0000000..394d223
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/23_containers/stack/requirements/explicit_instantiation/1_c++98.cc
@@ -0,0 +1,30 @@
+// { dg-options "-std=gnu++98" }
+// { dg-do compile }
+
+// Copyright (C) 2009-2017 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// This file tests explicit instantiation of library containers.
+
+#include <stack>
+
+template class std::stack<int>;
+
+struct NonDefaultConstructible : std::deque<int> {
+  NonDefaultConstructible(int) { }
+};
+template class std::stack<int, NonDefaultConstructible>;

Reply via email to