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