Here is another chunk of p1032. Jonthan, I plan to get it all except maybe string::copy. I can't figure out how to test without being able to create a constexpr string object. And anything I do will probably collide with your work on constexpr string. p1032 would be a tiny patch on top of that work anyway. Ed
Test on x86_64-linux. OK?
2019-11-15 Edward Smith-Rowland <3dw...@verizon.net> Implement the <iterator> part of C++20 p1032 Misc constexpr bits. * include/bits/stl_iterator.h (back_insert_iterator, back_inserter) (front_insert_iterator, front_inserter, insert_iterator, inserter): Make constexpr. * testsuite/24_iterators/insert_iterator/requirements/constexpr.cc: New. * testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc: New. * testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc: New. * testsuite/24_iterators/headers/iterator/synopsis_c++17.cc: Move inserter tests ... * testsuite/24_iterators/headers/iterator/inserters_c++17.cc: ... here. * testsuite/24_iterators/headers/iterator/inserters_c++20.cc: New.
Index: include/bits/stl_iterator.h =================================================================== --- include/bits/stl_iterator.h (revision 278302) +++ include/bits/stl_iterator.h (working copy) @@ -497,8 +497,12 @@ /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + constexpr back_insert_iterator() noexcept = default; +#endif + /// The only way to create this %iterator is with a container. - explicit + explicit _GLIBCXX20_CONSTEXPR back_insert_iterator(_Container& __x) : container(std::__addressof(__x)) { } @@ -521,7 +525,7 @@ return *this; } #else - back_insert_iterator& + _GLIBCXX20_CONSTEXPR back_insert_iterator& operator=(const typename _Container::value_type& __value) { container->push_back(__value); @@ -528,7 +532,7 @@ return *this; } - back_insert_iterator& + _GLIBCXX20_CONSTEXPR back_insert_iterator& operator=(typename _Container::value_type&& __value) { container->push_back(std::move(__value)); @@ -537,17 +541,17 @@ #endif /// Simply returns *this. - back_insert_iterator& + _GLIBCXX20_CONSTEXPR back_insert_iterator& operator*() { return *this; } /// Simply returns *this. (This %iterator does not @a move.) - back_insert_iterator& + _GLIBCXX20_CONSTEXPR back_insert_iterator& operator++() { return *this; } /// Simply returns *this. (This %iterator does not @a move.) - back_insert_iterator + _GLIBCXX20_CONSTEXPR back_insert_iterator operator++(int) { return *this; } }; @@ -564,7 +568,7 @@ * types for you. */ template<typename _Container> - inline back_insert_iterator<_Container> + inline _GLIBCXX20_CONSTEXPR back_insert_iterator<_Container> back_inserter(_Container& __x) { return back_insert_iterator<_Container>(__x); } @@ -589,8 +593,13 @@ /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + constexpr front_insert_iterator() noexcept = default; +#endif + /// The only way to create this %iterator is with a container. - explicit front_insert_iterator(_Container& __x) + explicit _GLIBCXX20_CONSTEXPR + front_insert_iterator(_Container& __x) : container(std::__addressof(__x)) { } /** @@ -612,14 +621,13 @@ return *this; } #else - front_insert_iterator& + _GLIBCXX20_CONSTEXPR front_insert_iterator& operator=(const typename _Container::value_type& __value) { container->push_front(__value); return *this; } - - front_insert_iterator& + _GLIBCXX20_CONSTEXPR front_insert_iterator& operator=(typename _Container::value_type&& __value) { container->push_front(std::move(__value)); @@ -628,17 +636,17 @@ #endif /// Simply returns *this. - front_insert_iterator& + _GLIBCXX20_CONSTEXPR front_insert_iterator& operator*() { return *this; } /// Simply returns *this. (This %iterator does not @a move.) - front_insert_iterator& + _GLIBCXX20_CONSTEXPR front_insert_iterator& operator++() { return *this; } /// Simply returns *this. (This %iterator does not @a move.) - front_insert_iterator + _GLIBCXX20_CONSTEXPR front_insert_iterator operator++(int) { return *this; } }; @@ -655,7 +663,7 @@ * types for you. */ template<typename _Container> - inline front_insert_iterator<_Container> + inline _GLIBCXX20_CONSTEXPR front_insert_iterator<_Container> front_inserter(_Container& __x) { return front_insert_iterator<_Container>(__x); } @@ -685,10 +693,15 @@ /// A nested typedef for the type of whatever container you used. typedef _Container container_type; +#if __cplusplus > 201703L + constexpr insert_iterator() = default; +#endif + /** * The only way to create this %iterator is with a container and an * initial position (a normal %iterator into the container). */ + _GLIBCXX20_CONSTEXPR insert_iterator(_Container& __x, typename _Container::iterator __i) : container(std::__addressof(__x)), iter(__i) {} @@ -724,7 +737,7 @@ return *this; } #else - insert_iterator& + _GLIBCXX20_CONSTEXPR insert_iterator& operator=(const typename _Container::value_type& __value) { iter = container->insert(iter, __value); @@ -732,7 +745,7 @@ return *this; } - insert_iterator& + _GLIBCXX20_CONSTEXPR insert_iterator& operator=(typename _Container::value_type&& __value) { iter = container->insert(iter, std::move(__value)); @@ -742,17 +755,17 @@ #endif /// Simply returns *this. - insert_iterator& + _GLIBCXX20_CONSTEXPR insert_iterator& operator*() { return *this; } /// Simply returns *this. (This %iterator does not @a move.) - insert_iterator& + _GLIBCXX20_CONSTEXPR insert_iterator& operator++() { return *this; } /// Simply returns *this. (This %iterator does not @a move.) - insert_iterator& + _GLIBCXX20_CONSTEXPR insert_iterator& operator++(int) { return *this; } }; @@ -770,7 +783,7 @@ * types for you. */ template<typename _Container, typename _Iterator> - inline insert_iterator<_Container> + inline _GLIBCXX20_CONSTEXPR insert_iterator<_Container> inserter(_Container& __x, _Iterator __i) { return insert_iterator<_Container>(__x, Index: testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc =================================================================== --- testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc (nonexistent) +++ testsuite/24_iterators/back_insert_iterator/requirements/constexpr.cc (working copy) @@ -0,0 +1,67 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// +// Copyright (C) 2019 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/>. + +#include <iterator> +#include <array> + +template<typename Tp> + struct listoid + { + using value_type = Tp; + using iterator = size_t; + + constexpr listoid() = default; + + constexpr void push_back(const value_type& value) { return; } + constexpr void push_back(value_type&& value) { return; } + constexpr void push_front(const value_type& value) { return; } + constexpr void push_front(value_type&& value) { return; } + constexpr iterator insert(iterator pos, const value_type& value) { return pos; } + constexpr iterator begin() noexcept { return _M_begin; } + constexpr iterator end() noexcept { return _M_end; } + + private: + size_t _M_begin = 0; + size_t _M_end = 0; + }; + +constexpr bool +test() +{ + listoid<int> l; + + auto ok = true; + const int route = 66; + + constexpr std::array<int, 2> b{89, 99}; + const std::back_insert_iterator<listoid<int>> bi(l); + std::copy(b.begin(), b.end(), bi); + auto nbi = std::back_inserter(l); + nbi = route; + nbi = 77; + + return ok; +} + +int +main() +{ + static_assert(test()); +} Index: testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc =================================================================== --- testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc (nonexistent) +++ testsuite/24_iterators/front_insert_iterator/requirements/constexpr.cc (working copy) @@ -0,0 +1,67 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// +// Copyright (C) 2019 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/>. + +#include <iterator> +#include <array> + +template<typename Tp> + struct listoid + { + using value_type = Tp; + using iterator = size_t; + + constexpr listoid() = default; + + constexpr void push_back(const value_type& value) { return; } + constexpr void push_back(value_type&& value) { return; } + constexpr void push_front(const value_type& value) { return; } + constexpr void push_front(value_type&& value) { return; } + constexpr iterator insert(iterator pos, const value_type& value) { return pos; } + constexpr iterator begin() noexcept { return _M_begin; } + constexpr iterator end() noexcept { return _M_end; } + + private: + size_t _M_begin = 0; + size_t _M_end = 0; + }; + +constexpr bool +test() +{ + listoid<int> l; + + auto ok = true; + const int route = 66; + + constexpr std::array<int, 2> f{-1, 0}; + const std::front_insert_iterator<listoid<int>> fi(l); + std::copy(f.begin(), f.end(), fi); + auto nfi = std::front_inserter(l); + nfi = route; + nfi = 77; + + return ok; +} + +int +main() +{ + static_assert(test()); +} Index: testsuite/24_iterators/headers/iterator/inserters_c++17.cc =================================================================== --- testsuite/24_iterators/headers/iterator/inserters_c++17.cc (nonexistent) +++ testsuite/24_iterators/headers/iterator/inserters_c++17.cc (working copy) @@ -0,0 +1,40 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } +// { dg-require-normal-namespace "" } + +// Copyright (C) 2019 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/>. + +#include <iterator> + +namespace std { + + template <class Container> class back_insert_iterator; + + template <class Container> + back_insert_iterator<Container> back_inserter(Container& x); + + template <class Container> class front_insert_iterator; + + template <class Container> + front_insert_iterator<Container> front_inserter(Container& x); + + template <class Container> class insert_iterator; + + template <class Container, class Iterator> + insert_iterator<Container> inserter(Container& x, Iterator i); +} Index: testsuite/24_iterators/headers/iterator/inserters_c++20.cc =================================================================== --- testsuite/24_iterators/headers/iterator/inserters_c++20.cc (nonexistent) +++ testsuite/24_iterators/headers/iterator/inserters_c++20.cc (working copy) @@ -0,0 +1,40 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile } +// { dg-require-normal-namespace "" } + +// Copyright (C) 2019 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/>. + +#include <iterator> + +namespace std { + + template <class Container> class back_insert_iterator; + + template <class Container> + constexpr back_insert_iterator<Container> back_inserter(Container& x); + + template <class Container> class front_insert_iterator; + + template <class Container> + constexpr front_insert_iterator<Container> front_inserter(Container& x); + + template <class Container> class insert_iterator; + + template <class Container, class Iterator> + constexpr insert_iterator<Container> inserter(Container& x, Iterator i); +} Index: testsuite/24_iterators/headers/iterator/synopsis_c++17.cc =================================================================== --- testsuite/24_iterators/headers/iterator/synopsis_c++17.cc (revision 278302) +++ testsuite/24_iterators/headers/iterator/synopsis_c++17.cc (working copy) @@ -89,21 +89,6 @@ template <class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(const Iterator&); - template <class Container> class back_insert_iterator; - - template <class Container> - back_insert_iterator<Container> back_inserter(Container& x); - - template <class Container> class front_insert_iterator; - - template <class Container> - front_insert_iterator<Container> front_inserter(Container& x); - - template <class Container> class insert_iterator; - - template <class Container, class Iterator> - insert_iterator<Container> inserter(Container& x, Iterator i); - template <class Iterator> class move_iterator; template <class Iterator1, class Iterator2> Index: testsuite/24_iterators/insert_iterator/requirements/constexpr.cc =================================================================== --- testsuite/24_iterators/insert_iterator/requirements/constexpr.cc (nonexistent) +++ testsuite/24_iterators/insert_iterator/requirements/constexpr.cc (working copy) @@ -0,0 +1,68 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// +// Copyright (C) 2019 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/>. + +#include <iterator> +#include <array> + +template<typename Tp> + struct listoid + { + using value_type = Tp; + using iterator = size_t; + + constexpr listoid() = default; + + constexpr void push_back(const value_type& value) { return; } + constexpr void push_back(value_type&& value) { return; } + constexpr void push_front(const value_type& value) { return; } + constexpr void push_front(value_type&& value) { return; } + constexpr iterator insert(iterator pos, const value_type& value) { return pos; } + constexpr iterator begin() noexcept { return _M_begin; } + constexpr iterator end() noexcept { return _M_end; } + + private: + size_t _M_begin = 0; + size_t _M_end = 0; + }; + +constexpr bool +test() +{ + listoid<int> l; + + auto ok = true; + const int route = 66; + + constexpr std::array<int, 5> a{1, 2, 3, 4, 5}; + const auto liter = l.begin() + 1; + const std::insert_iterator<listoid<int>> ii(l, liter); + std::copy(a.begin(), a.end(), ii); + auto nii = std::inserter(l, liter); + nii = route; + nii = 77; + + return ok; +} + +int +main() +{ + static_assert(test()); +}