diff options
Diffstat (limited to 'libstdc++-v3/include')
52 files changed, 3670 insertions, 189 deletions
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 236c2d6059f..add2277df80 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -37,6 +37,7 @@ std_headers = \ ${std_srcdir}/complex \ ${std_srcdir}/condition_variable \ ${std_srcdir}/deque \ + ${std_srcdir}/filesystem \ ${std_srcdir}/forward_list \ ${std_srcdir}/fstream \ ${std_srcdir}/functional \ @@ -104,6 +105,10 @@ bits_headers = \ ${bits_srcdir}/enable_special_members.h \ ${bits_srcdir}/forward_list.h \ ${bits_srcdir}/forward_list.tcc \ + ${bits_srcdir}/fs_dir.h \ + ${bits_srcdir}/fs_fwd.h \ + ${bits_srcdir}/fs_ops.h \ + ${bits_srcdir}/fs_path.h \ ${bits_srcdir}/fstream.tcc \ ${bits_srcdir}/functexcept.h \ ${bits_srcdir}/functional_hash.h \ @@ -125,7 +130,6 @@ bits_headers = \ ${bits_srcdir}/locale_facets_nonio.tcc \ ${bits_srcdir}/localefwd.h \ ${bits_srcdir}/mask_array.h \ - ${bits_srcdir}/specfun.h \ ${bits_srcdir}/memoryfwd.h \ ${bits_srcdir}/move.h \ ${bits_srcdir}/node_handle.h \ @@ -156,6 +160,7 @@ bits_headers = \ ${bits_srcdir}/shared_ptr_atomic.h \ ${bits_srcdir}/shared_ptr_base.h \ ${bits_srcdir}/slice_array.h \ + ${bits_srcdir}/specfun.h \ ${bits_srcdir}/sstream.tcc \ ${bits_srcdir}/std_abs.h \ ${bits_srcdir}/std_function.h \ @@ -1026,7 +1031,7 @@ stamp-bits: ${bits_headers} @$(STAMP) stamp-bits stamp-bits-sup: stamp-bits ${bits_sup_headers} - @-cd ${bits_builddir} && $(LN_S) $? . 2>/dev/null + @-cd ${bits_builddir} && $(LN_S) ${bits_sup_headers} . 2>/dev/null @$(STAMP) stamp-bits-sup stamp-c_base: ${c_base_headers} diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 39dfede549b..0e3fe49142e 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -330,6 +330,7 @@ std_headers = \ ${std_srcdir}/complex \ ${std_srcdir}/condition_variable \ ${std_srcdir}/deque \ + ${std_srcdir}/filesystem \ ${std_srcdir}/forward_list \ ${std_srcdir}/fstream \ ${std_srcdir}/functional \ @@ -397,6 +398,10 @@ bits_headers = \ ${bits_srcdir}/enable_special_members.h \ ${bits_srcdir}/forward_list.h \ ${bits_srcdir}/forward_list.tcc \ + ${bits_srcdir}/fs_dir.h \ + ${bits_srcdir}/fs_fwd.h \ + ${bits_srcdir}/fs_ops.h \ + ${bits_srcdir}/fs_path.h \ ${bits_srcdir}/fstream.tcc \ ${bits_srcdir}/functexcept.h \ ${bits_srcdir}/functional_hash.h \ @@ -418,7 +423,6 @@ bits_headers = \ ${bits_srcdir}/locale_facets_nonio.tcc \ ${bits_srcdir}/localefwd.h \ ${bits_srcdir}/mask_array.h \ - ${bits_srcdir}/specfun.h \ ${bits_srcdir}/memoryfwd.h \ ${bits_srcdir}/move.h \ ${bits_srcdir}/node_handle.h \ @@ -449,6 +453,7 @@ bits_headers = \ ${bits_srcdir}/shared_ptr_atomic.h \ ${bits_srcdir}/shared_ptr_base.h \ ${bits_srcdir}/slice_array.h \ + ${bits_srcdir}/specfun.h \ ${bits_srcdir}/sstream.tcc \ ${bits_srcdir}/std_abs.h \ ${bits_srcdir}/std_function.h \ @@ -1475,7 +1480,7 @@ stamp-bits: ${bits_headers} @$(STAMP) stamp-bits stamp-bits-sup: stamp-bits ${bits_sup_headers} - @-cd ${bits_builddir} && $(LN_S) $? . 2>/dev/null + @-cd ${bits_builddir} && $(LN_S) ${bits_sup_headers} . 2>/dev/null @$(STAMP) stamp-bits-sup stamp-c_base: ${c_base_headers} diff --git a/libstdc++-v3/include/bits/fs_dir.h b/libstdc++-v3/include/bits/fs_dir.h new file mode 100644 index 00000000000..579a269711e --- /dev/null +++ b/libstdc++-v3/include/bits/fs_dir.h @@ -0,0 +1,525 @@ +// Filesystem directory utilities -*- C++ -*- + +// Copyright (C) 2014-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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/fs_dir.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{filesystem} + */ + +#ifndef _GLIBCXX_FS_DIR_H +#define _GLIBCXX_FS_DIR_H 1 + +#if __cplusplus >= 201703L +# include <typeinfo> +# include <ext/concurrence.h> +# include <bits/unique_ptr.h> +# include <bits/shared_ptr.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace filesystem +{ + /** + * @ingroup filesystem + * @{ + */ + + class file_status + { + public: + // constructors and destructor + file_status() noexcept : file_status(file_type::none) {} + + explicit + file_status(file_type __ft, perms __prms = perms::unknown) noexcept + : _M_type(__ft), _M_perms(__prms) { } + + file_status(const file_status&) noexcept = default; + file_status(file_status&&) noexcept = default; + ~file_status() = default; + + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&) noexcept = default; + + // observers + file_type type() const noexcept { return _M_type; } + perms permissions() const noexcept { return _M_perms; } + + // modifiers + void type(file_type __ft) noexcept { _M_type = __ft; } + void permissions(perms __prms) noexcept { _M_perms = __prms; } + + private: + file_type _M_type; + perms _M_perms; + }; + +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + struct _Dir; + class directory_iterator; + class recursive_directory_iterator; + + class directory_entry + { + public: + // constructors and destructor + directory_entry() noexcept = default; + directory_entry(const directory_entry&) = default; + directory_entry(directory_entry&&) noexcept = default; + + explicit + directory_entry(const filesystem::path& __p) + : _M_path(__p) + { refresh(); } + + directory_entry(const filesystem::path& __p, error_code& __ec) + : _M_path(__p) + { + refresh(__ec); + if (__ec) + _M_path.clear(); + } + + ~directory_entry() = default; + + // modifiers + directory_entry& operator=(const directory_entry&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + void + assign(const filesystem::path& __p) + { + _M_path = __p; + refresh(); + } + + void + assign(const filesystem::path& __p, error_code& __ec) + { + _M_path = __p; + refresh(__ec); + } + + void + replace_filename(const filesystem::path& __p) + { + _M_path.replace_filename(__p); + refresh(); + } + + void + replace_filename(const filesystem::path& __p, error_code& __ec) + { + _M_path.replace_filename(__p); + refresh(__ec); + } + + void refresh() { _M_type = symlink_status().type(); } + void refresh(error_code& __ec) { _M_type = symlink_status(__ec).type(); } + + // observers + const filesystem::path& path() const noexcept { return _M_path; } + operator const filesystem::path& () const noexcept { return _M_path; } + + bool + exists() const + { return filesystem::exists(file_status{_M_file_type()}); } + + bool + exists(error_code& __ec) const noexcept + { return filesystem::exists(file_status{_M_file_type(__ec)}); } + + bool + is_block_file() const + { return _M_file_type() == file_type::block; } + + bool + is_block_file(error_code& __ec) const noexcept + { return _M_file_type(__ec) == file_type::block; } + + bool + is_character_file() const + { return _M_file_type() == file_type::character; } + + bool + is_character_file(error_code& __ec) const noexcept + { return _M_file_type(__ec) == file_type::character; } + + bool + is_directory() const + { return _M_file_type() == file_type::directory; } + + bool + is_directory(error_code& __ec) const noexcept + { return _M_file_type(__ec) == file_type::directory; } + + bool + is_fifo() const + { return _M_file_type() == file_type::fifo; } + + bool + is_fifo(error_code& __ec) const noexcept + { return _M_file_type(__ec) == file_type::fifo; } + + bool + is_other() const + { return filesystem::is_other(file_status{_M_file_type()}); } + + bool + is_other(error_code& __ec) const noexcept + { return filesystem::is_other(file_status{_M_file_type(__ec)}); } + + bool + is_regular_file() const + { return _M_file_type() == file_type::regular; } + + bool + is_regular_file(error_code& __ec) const noexcept + { return _M_file_type(__ec) == file_type::regular; } + + bool + is_socket() const + { return _M_file_type() == file_type::socket; } + + bool + is_socket(error_code& __ec) const noexcept + { return _M_file_type(__ec) == file_type::socket; } + + bool + is_symlink() const + { + if (_M_type != file_type::none) + return _M_type == file_type::symlink; + return symlink_status().type() == file_type::symlink; + } + + bool + is_symlink(error_code& __ec) const noexcept + { + if (_M_type != file_type::none) + return _M_type == file_type::symlink; + return symlink_status(__ec).type() == file_type::symlink; + } + + uintmax_t + file_size() const + { return filesystem::file_size(_M_path); } + + uintmax_t + file_size(error_code& __ec) const noexcept + { return filesystem::file_size(_M_path, __ec); } + + uintmax_t + hard_link_count() const + { return filesystem::hard_link_count(_M_path); } + + uintmax_t + hard_link_count(error_code& __ec) const noexcept + { return filesystem::hard_link_count(_M_path, __ec); } + + file_time_type + last_write_time() const + { return filesystem::last_write_time(_M_path); } + + + file_time_type + last_write_time(error_code& __ec) const noexcept + { return filesystem::last_write_time(_M_path, __ec); } + + file_status + status() const + { return filesystem::status(_M_path); } + + file_status + status(error_code& __ec) const noexcept + { return filesystem::status(_M_path, __ec); } + + file_status + symlink_status() const + { return filesystem::symlink_status(_M_path); } + + file_status + symlink_status(error_code& __ec) const noexcept + { return filesystem::symlink_status(_M_path, __ec); } + + bool + operator< (const directory_entry& __rhs) const noexcept + { return _M_path < __rhs._M_path; } + + bool + operator==(const directory_entry& __rhs) const noexcept + { return _M_path == __rhs._M_path; } + + bool + operator!=(const directory_entry& __rhs) const noexcept + { return _M_path != __rhs._M_path; } + + bool + operator<=(const directory_entry& __rhs) const noexcept + { return _M_path <= __rhs._M_path; } + + bool + operator> (const directory_entry& __rhs) const noexcept + { return _M_path > __rhs._M_path; } + + bool + operator>=(const directory_entry& __rhs) const noexcept + { return _M_path >= __rhs._M_path; } + + private: + friend class _Dir; + friend class directory_iterator; + friend class recursive_directory_iterator; + + directory_entry(const filesystem::path& __p, file_type __t) + : _M_path(__p), _M_type(__t) + { } + + // Equivalent to status().type() but uses cached value, if any. + file_type + _M_file_type() const + { + if (_M_type != file_type::none && _M_type != file_type::symlink) + return _M_type; + return status().type(); + } + + // Equivalent to status(__ec).type() but uses cached value, if any. + file_type + _M_file_type(error_code& __ec) const noexcept + { + if (_M_type != file_type::none && _M_type != file_type::symlink) + return _M_type; + return status(__ec).type(); + } + + filesystem::path _M_path; + file_type _M_type = file_type::none; + }; + + struct __directory_iterator_proxy + { + const directory_entry& operator*() const& noexcept { return _M_entry; } + + directory_entry operator*() && noexcept { return std::move(_M_entry); } + + private: + friend class directory_iterator; + friend class recursive_directory_iterator; + + explicit + __directory_iterator_proxy(const directory_entry& __e) : _M_entry(__e) { } + + directory_entry _M_entry; + }; + + class directory_iterator + { + public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef const directory_entry* pointer; + typedef const directory_entry& reference; + typedef input_iterator_tag iterator_category; + + directory_iterator() = default; + + explicit + directory_iterator(const path& __p) + : directory_iterator(__p, directory_options::none, nullptr) { } + + directory_iterator(const path& __p, directory_options __options) + : directory_iterator(__p, __options, nullptr) { } + + directory_iterator(const path& __p, error_code& __ec) + : directory_iterator(__p, directory_options::none, __ec) { } + + directory_iterator(const path& __p, directory_options __options, + error_code& __ec) + : directory_iterator(__p, __options, &__ec) { } + + directory_iterator(const directory_iterator& __rhs) = default; + + directory_iterator(directory_iterator&& __rhs) noexcept = default; + + ~directory_iterator() = default; + + directory_iterator& + operator=(const directory_iterator& __rhs) = default; + + directory_iterator& + operator=(directory_iterator&& __rhs) noexcept = default; + + const directory_entry& operator*() const; + const directory_entry* operator->() const { return &**this; } + directory_iterator& operator++(); + directory_iterator& increment(error_code& __ec); + + __directory_iterator_proxy operator++(int) + { + __directory_iterator_proxy __pr{**this}; + ++*this; + return __pr; + } + + private: + directory_iterator(const path&, directory_options, error_code*); + + friend bool + operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs); + + friend class recursive_directory_iterator; + + std::shared_ptr<_Dir> _M_dir; + }; + + inline directory_iterator + begin(directory_iterator __iter) noexcept + { return __iter; } + + inline directory_iterator + end(directory_iterator) noexcept + { return directory_iterator(); } + + inline bool + operator==(const directory_iterator& __lhs, const directory_iterator& __rhs) + { + return !__rhs._M_dir.owner_before(__lhs._M_dir) + && !__lhs._M_dir.owner_before(__rhs._M_dir); + } + + inline bool + operator!=(const directory_iterator& __lhs, const directory_iterator& __rhs) + { return !(__lhs == __rhs); } + + class recursive_directory_iterator + { + public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef const directory_entry* pointer; + typedef const directory_entry& reference; + typedef input_iterator_tag iterator_category; + + recursive_directory_iterator() = default; + + explicit + recursive_directory_iterator(const path& __p) + : recursive_directory_iterator(__p, directory_options::none, nullptr) { } + + recursive_directory_iterator(const path& __p, directory_options __options) + : recursive_directory_iterator(__p, __options, nullptr) { } + + recursive_directory_iterator(const path& __p, directory_options __options, + error_code& __ec) + : recursive_directory_iterator(__p, __options, &__ec) { } + + recursive_directory_iterator(const path& __p, error_code& __ec) + : recursive_directory_iterator(__p, directory_options::none, &__ec) { } + + recursive_directory_iterator( + const recursive_directory_iterator&) = default; + + recursive_directory_iterator(recursive_directory_iterator&&) = default; + + ~recursive_directory_iterator(); + + // observers + directory_options options() const { return _M_options; } + int depth() const; + bool recursion_pending() const { return _M_pending; } + + const directory_entry& operator*() const; + const directory_entry* operator->() const { return &**this; } + + // modifiers + recursive_directory_iterator& + operator=(const recursive_directory_iterator& __rhs) noexcept; + recursive_directory_iterator& + operator=(recursive_directory_iterator&& __rhs) noexcept; + + recursive_directory_iterator& operator++(); + recursive_directory_iterator& increment(error_code& __ec); + + __directory_iterator_proxy operator++(int) + { + __directory_iterator_proxy __pr{**this}; + ++*this; + return __pr; + } + + void pop(); + void pop(error_code&); + + void disable_recursion_pending() { _M_pending = false; } + + private: + recursive_directory_iterator(const path&, directory_options, error_code*); + + friend bool + operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs); + + struct _Dir_stack; + std::shared_ptr<_Dir_stack> _M_dirs; + directory_options _M_options = {}; + bool _M_pending = false; + }; + + inline recursive_directory_iterator + begin(recursive_directory_iterator __iter) noexcept + { return __iter; } + + inline recursive_directory_iterator + end(recursive_directory_iterator) noexcept + { return recursive_directory_iterator(); } + + inline bool + operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) + { + return !__rhs._M_dirs.owner_before(__lhs._M_dirs) + && !__lhs._M_dirs.owner_before(__rhs._M_dirs); + } + + inline bool + operator!=(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) + { return !(__lhs == __rhs); } + +_GLIBCXX_END_NAMESPACE_CXX11 + + // @} group filesystem +} // namespace filesystem + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_FS_DIR_H diff --git a/libstdc++-v3/include/bits/fs_fwd.h b/libstdc++-v3/include/bits/fs_fwd.h new file mode 100644 index 00000000000..f408a39b974 --- /dev/null +++ b/libstdc++-v3/include/bits/fs_fwd.h @@ -0,0 +1,348 @@ +// Filesystem declarations -*- C++ -*- + +// Copyright (C) 2014-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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/fs_fwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{filesystem} + */ + +#ifndef _GLIBCXX_FS_FWD_H +#define _GLIBCXX_FS_FWD_H 1 + +#if __cplusplus >= 201703L + +#include <system_error> +#include <cstdint> +#include <chrono> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace filesystem +{ +#if _GLIBCXX_USE_CXX11_ABI +inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +#endif + + /** + * @defgroup filesystem Filesystem + * + * Utilities for performing operations on file systems and their components, + * such as paths, regular files, and directories. + * + * @{ + */ + + class file_status; +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + class path; + class filesystem_error; + class directory_entry; + class directory_iterator; + class recursive_directory_iterator; +_GLIBCXX_END_NAMESPACE_CXX11 + + struct space_info + { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; + }; + + enum class file_type : signed char { + none = 0, not_found = -1, regular = 1, directory = 2, symlink = 3, + block = 4, character = 5, fifo = 6, socket = 7, unknown = 8 + }; + + /// Bitmask type + enum class copy_options : unsigned short { + none = 0, + skip_existing = 1, overwrite_existing = 2, update_existing = 4, + recursive = 8, + copy_symlinks = 16, skip_symlinks = 32, + directories_only = 64, create_symlinks = 128, create_hard_links = 256 + }; + + constexpr copy_options + operator&(copy_options __x, copy_options __y) noexcept + { + using __utype = typename std::underlying_type<copy_options>::type; + return static_cast<copy_options>( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr copy_options + operator|(copy_options __x, copy_options __y) noexcept + { + using __utype = typename std::underlying_type<copy_options>::type; + return static_cast<copy_options>( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr copy_options + operator^(copy_options __x, copy_options __y) noexcept + { + using __utype = typename std::underlying_type<copy_options>::type; + return static_cast<copy_options>( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr copy_options + operator~(copy_options __x) noexcept + { + using __utype = typename std::underlying_type<copy_options>::type; + return static_cast<copy_options>(~static_cast<__utype>(__x)); + } + + inline copy_options& + operator&=(copy_options& __x, copy_options __y) noexcept + { return __x = __x & __y; } + + inline copy_options& + operator|=(copy_options& __x, copy_options __y) noexcept + { return __x = __x | __y; } + + inline copy_options& + operator^=(copy_options& __x, copy_options __y) noexcept + { return __x = __x ^ __y; } + + + /// Bitmask type + enum class perms : unsigned { + none = 0, + owner_read = 0400, + owner_write = 0200, + owner_exec = 0100, + owner_all = 0700, + group_read = 040, + group_write = 020, + group_exec = 010, + group_all = 070, + others_read = 04, + others_write = 02, + others_exec = 01, + others_all = 07, + all = 0777, + set_uid = 04000, + set_gid = 02000, + sticky_bit = 01000, + mask = 07777, + unknown = 0xFFFF, + }; + + constexpr perms + operator&(perms __x, perms __y) noexcept + { + using __utype = typename std::underlying_type<perms>::type; + return static_cast<perms>( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr perms + operator|(perms __x, perms __y) noexcept + { + using __utype = typename std::underlying_type<perms>::type; + return static_cast<perms>( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr perms + operator^(perms __x, perms __y) noexcept + { + using __utype = typename std::underlying_type<perms>::type; + return static_cast<perms>( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr perms + operator~(perms __x) noexcept + { + using __utype = typename std::underlying_type<perms>::type; + return static_cast<perms>(~static_cast<__utype>(__x)); + } + + inline perms& + operator&=(perms& __x, perms __y) noexcept + { return __x = __x & __y; } + + inline perms& + operator|=(perms& __x, perms __y) noexcept + { return __x = __x | __y; } + + inline perms& + operator^=(perms& __x, perms __y) noexcept + { return __x = __x ^ __y; } + + /// Bitmask type + enum class perm_options : unsigned { + replace = 0x1, + add = 0x2, + remove = 0x4, + nofollow = 0x8 + }; + + constexpr perm_options + operator&(perm_options __x, perm_options __y) noexcept + { + using __utype = typename std::underlying_type<perm_options>::type; + return static_cast<perm_options>( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr perm_options + operator|(perm_options __x, perm_options __y) noexcept + { + using __utype = typename std::underlying_type<perm_options>::type; + return static_cast<perm_options>( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr perm_options + operator^(perm_options __x, perm_options __y) noexcept + { + using __utype = typename std::underlying_type<perm_options>::type; + return static_cast<perm_options>( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr perm_options + operator~(perm_options __x) noexcept + { + using __utype = typename std::underlying_type<perm_options>::type; + return static_cast<perm_options>(~static_cast<__utype>(__x)); + } + + inline perm_options& + operator&=(perm_options& __x, perm_options __y) noexcept + { return __x = __x & __y; } + + inline perm_options& + operator|=(perm_options& __x, perm_options __y) noexcept + { return __x = __x | __y; } + + inline perm_options& + operator^=(perm_options& __x, perm_options __y) noexcept + { return __x = __x ^ __y; } + + // Bitmask type + enum class directory_options : unsigned char { + none = 0, follow_directory_symlink = 1, skip_permission_denied = 2 + }; + + constexpr directory_options + operator&(directory_options __x, directory_options __y) noexcept + { + using __utype = typename std::underlying_type<directory_options>::type; + return static_cast<directory_options>( + static_cast<__utype>(__x) & static_cast<__utype>(__y)); + } + + constexpr directory_options + operator|(directory_options __x, directory_options __y) noexcept + { + using __utype = typename std::underlying_type<directory_options>::type; + return static_cast<directory_options>( + static_cast<__utype>(__x) | static_cast<__utype>(__y)); + } + + constexpr directory_options + operator^(directory_options __x, directory_options __y) noexcept + { + using __utype = typename std::underlying_type<directory_options>::type; + return static_cast<directory_options>( + static_cast<__utype>(__x) ^ static_cast<__utype>(__y)); + } + + constexpr directory_options + operator~(directory_options __x) noexcept + { + using __utype = typename std::underlying_type<directory_options>::type; + return static_cast<directory_options>(~static_cast<__utype>(__x)); + } + + inline directory_options& + operator&=(directory_options& __x, directory_options __y) noexcept + { return __x = __x & __y; } + + inline directory_options& + operator|=(directory_options& __x, directory_options __y) noexcept + { return __x = __x | __y; } + + inline directory_options& + operator^=(directory_options& __x, directory_options __y) noexcept + { return __x = __x ^ __y; } + + using file_time_type = std::chrono::system_clock::time_point; + + // operational functions + + void copy(const path& __from, const path& __to, copy_options __options); + void copy(const path& __from, const path& __to, copy_options __options, + error_code&) noexcept; + + bool copy_file(const path& __from, const path& __to, copy_options __option); + bool copy_file(const path& __from, const path& __to, copy_options __option, + error_code&) noexcept; + + path current_path(); + + bool exists(file_status) noexcept; + + bool is_other(file_status) noexcept; + + uintmax_t file_size(const path&); + uintmax_t file_size(const path&, error_code&) noexcept; + uintmax_t hard_link_count(const path&); + uintmax_t hard_link_count(const path&, error_code&) noexcept; + file_time_type last_write_time(const path&); + file_time_type last_write_time(const path&, error_code&) noexcept; + + void permissions(const path&, perms, perm_options, error_code&); + + path proximate(const path& __p, const path& __base, error_code& __ec); + path proximate(const path& __p, const path& __base, error_code& __ec); + + path relative(const path& __p, const path& __base, error_code& __ec); + + file_status status(const path&); + file_status status(const path&, error_code&) noexcept; + + bool status_known(file_status) noexcept; + + file_status symlink_status(const path&); + file_status symlink_status(const path&, error_code&) noexcept; + + bool is_regular_file(file_status) noexcept; + bool is_symlink(file_status) noexcept; + + // @} group filesystem +} // namespace filesystem + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_FS_FWD_H diff --git a/libstdc++-v3/include/bits/fs_ops.h b/libstdc++-v3/include/bits/fs_ops.h new file mode 100644 index 00000000000..075d61e2a63 --- /dev/null +++ b/libstdc++-v3/include/bits/fs_ops.h @@ -0,0 +1,311 @@ +// Filesystem operational functions -*- C++ -*- + +// Copyright (C) 2014-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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/fs_fwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{filesystem} + */ + +#ifndef _GLIBCXX_FS_OPS_H +#define _GLIBCXX_FS_OPS_H 1 + +#if __cplusplus >= 201703L + +#include <cstdint> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace filesystem +{ + /** + * @ingroup filesystem + * @{ + */ + + path absolute(const path& __p); + path absolute(const path& __p, error_code& __ec); + + path canonical(const path& __p); + path canonical(const path& __p, error_code& __ec); + + inline void + copy(const path& __from, const path& __to) + { copy(__from, __to, copy_options::none); } + + inline void + copy(const path& __from, const path& __to, error_code& __ec) + { copy(__from, __to, copy_options::none, __ec); } + + void copy(const path& __from, const path& __to, copy_options __options); + void copy(const path& __from, const path& __to, copy_options __options, + error_code& __ec); + + inline bool + copy_file(const path& __from, const path& __to) + { return copy_file(__from, __to, copy_options::none); } + + inline bool + copy_file(const path& __from, const path& __to, error_code& __ec) + { return copy_file(__from, __to, copy_options::none, __ec); } + + bool copy_file(const path& __from, const path& __to, copy_options __option); + bool copy_file(const path& __from, const path& __to, copy_options __option, + error_code& __ec); + + void copy_symlink(const path& __existing_symlink, const path& __new_symlink); + void copy_symlink(const path& __existing_symlink, const path& __new_symlink, + error_code& __ec) noexcept; + + bool create_directories(const path& __p); + bool create_directories(const path& __p, error_code& __ec); + + bool create_directory(const path& __p); + bool create_directory(const path& __p, error_code& __ec) noexcept; + + bool create_directory(const path& __p, const path& attributes); + bool create_directory(const path& __p, const path& attributes, + error_code& __ec) noexcept; + + void create_directory_symlink(const path& __to, const path& __new_symlink); + void create_directory_symlink(const path& __to, const path& __new_symlink, + error_code& __ec) noexcept; + + void create_hard_link(const path& __to, const path& __new_hard_link); + void create_hard_link(const path& __to, const path& __new_hard_link, + error_code& __ec) noexcept; + + void create_symlink(const path& __to, const path& __new_symlink); + void create_symlink(const path& __to, const path& __new_symlink, + error_code& __ec) noexcept; + + path current_path(); + path current_path(error_code& __ec); + void current_path(const path& __p); + void current_path(const path& __p, error_code& __ec) noexcept; + + bool + equivalent(const path& __p1, const path& __p2); + + bool + equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept; + + inline bool + exists(file_status __s) noexcept + { return status_known(__s) && __s.type() != file_type::not_found; } + + inline bool + exists(const path& __p) + { return exists(status(__p)); } + + inline bool + exists(const path& __p, error_code& __ec) noexcept + { + auto __s = status(__p, __ec); + if (status_known(__s)) + __ec.clear(); + return exists(__s); + } + + uintmax_t file_size(const path& __p); + uintmax_t file_size(const path& __p, error_code& __ec) noexcept; + + uintmax_t hard_link_count(const path& __p); + uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept; + + inline bool + is_block_file(file_status __s) noexcept + { return __s.type() == file_type::block; } + + inline bool + is_block_file(const path& __p) + { return is_block_file(status(__p)); } + + inline bool + is_block_file(const path& __p, error_code& __ec) noexcept + { return is_block_file(status(__p, __ec)); } + + inline bool + is_character_file(file_status __s) noexcept + { return __s.type() == file_type::character; } + + inline bool + is_character_file(const path& __p) + { return is_character_file(status(__p)); } + + inline bool + is_character_file(const path& __p, error_code& __ec) noexcept + { return is_character_file(status(__p, __ec)); } + + inline bool + is_directory(file_status __s) noexcept + { return __s.type() == file_type::directory; } + + inline bool + is_directory(const path& __p) + { return is_directory(status(__p)); } + + inline bool + is_directory(const path& __p, error_code& __ec) noexcept + { return is_directory(status(__p, __ec)); } + + bool is_empty(const path& __p); + bool is_empty(const path& __p, error_code& __ec); + + inline bool + is_fifo(file_status __s) noexcept + { return __s.type() == file_type::fifo; } + + inline bool + is_fifo(const path& __p) + { return is_fifo(status(__p)); } + + inline bool + is_fifo(const path& __p, error_code& __ec) noexcept + { return is_fifo(status(__p, __ec)); } + + inline bool + is_other(file_status __s) noexcept + { + return exists(__s) && !is_regular_file(__s) && !is_directory(__s) + && !is_symlink(__s); + } + + inline bool + is_other(const path& __p) + { return is_other(status(__p)); } + + inline bool + is_other(const path& __p, error_code& __ec) noexcept + { return is_other(status(__p, __ec)); } + + inline bool + is_regular_file(file_status __s) noexcept + { return __s.type() == file_type::regular; } + + inline bool + is_regular_file(const path& __p) + { return is_regular_file(status(__p)); } + + inline bool + is_regular_file(const path& __p, error_code& __ec) noexcept + { return is_regular_file(status(__p, __ec)); } + + inline bool + is_socket(file_status __s) noexcept + { return __s.type() == file_type::socket; } + + inline bool + is_socket(const path& __p) + { return is_socket(status(__p)); } + + inline bool + is_socket(const path& __p, error_code& __ec) noexcept + { return is_socket(status(__p, __ec)); } + + inline bool + is_symlink(file_status __s) noexcept + { return __s.type() == file_type::symlink; } + + inline bool + is_symlink(const path& __p) + { return is_symlink(symlink_status(__p)); } + + inline bool + is_symlink(const path& __p, error_code& __ec) noexcept + { return is_symlink(symlink_status(__p, __ec)); } + + file_time_type last_write_time(const path& __p); + file_time_type last_write_time(const path& __p, error_code& __ec) noexcept; + void last_write_time(const path& __p, file_time_type __new_time); + void last_write_time(const path& __p, file_time_type __new_time, + error_code& __ec) noexcept; + + void + permissions(const path& __p, perms __prms, + perm_options __opts = perm_options::replace); + + inline void + permissions(const path& __p, perms __prms, error_code& __ec) noexcept + { permissions(__p, __prms, perm_options::replace, __ec); } + + void + permissions(const path& __p, perms __prms, perm_options __opts, + error_code& __ec); + + inline path proximate(const path& __p, error_code& __ec) + { return proximate(__p, current_path(), __ec); } + + path proximate(const path& __p, const path& __base = current_path()); + path proximate(const path& __p, const path& __base, error_code& __ec); + + path read_symlink(const path& __p); + path read_symlink(const path& __p, error_code& __ec); + + inline path relative(const path& __p, error_code& __ec) + { return relative(__p, current_path(), __ec); } + + path relative(const path& __p, const path& __base = current_path()); + path relative(const path& __p, const path& __base, error_code& __ec); + + bool remove(const path& __p); + bool remove(const path& __p, error_code& __ec) noexcept; + + uintmax_t remove_all(const path& __p); + uintmax_t remove_all(const path& __p, error_code& __ec); + + void rename(const path& __from, const path& __to); + void rename(const path& __from, const path& __to, error_code& __ec) noexcept; + + void resize_file(const path& __p, uintmax_t __size); + void resize_file(const path& __p, uintmax_t __size, error_code& __ec) noexcept; + + space_info space(const path& __p); + space_info space(const path& __p, error_code& __ec) noexcept; + + file_status status(const path& __p); + file_status status(const path& __p, error_code& __ec) noexcept; + + inline bool status_known(file_status __s) noexcept + { return __s.type() != file_type::none; } + + file_status symlink_status(const path& __p); + file_status symlink_status(const path& __p, error_code& __ec) noexcept; + + path temp_directory_path(); + path temp_directory_path(error_code& __ec); + + path weakly_canonical(const path& __p); + path weakly_canonical(const path& __p, error_code& __ec); + + // @} group filesystem +} // namespace filesystem + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_FS_OPS_H diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h new file mode 100644 index 00000000000..7d97cdfbb81 --- /dev/null +++ b/libstdc++-v3/include/bits/fs_path.h @@ -0,0 +1,1166 @@ +// Class filesystem::path -*- C++ -*- + +// Copyright (C) 2014-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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/fs_path.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{filesystem} + */ + +#ifndef _GLIBCXX_FS_PATH_H +#define _GLIBCXX_FS_PATH_H 1 + +#if __cplusplus >= 201703L + +#include <utility> +#include <type_traits> +#include <vector> +#include <locale> +#include <iosfwd> +#include <codecvt> +#include <string_view> +#include <system_error> +#include <bits/stl_algobase.h> +#include <bits/quoted_string.h> +#include <bits/locale_conv.h> + +#if defined(_WIN32) && !defined(__CYGWIN__) +# define _GLIBCXX_FILESYSTEM_IS_WINDOWS 1 +# include <algorithm> +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace filesystem +{ +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + + /** + * @ingroup filesystem + * @{ + */ + + /// A filesystem path. + class path + { + template<typename _CharT> + struct __is_encoded_char : std::false_type { }; + + template<typename _Iter, + typename _Iter_traits = std::iterator_traits<_Iter>> + using __is_path_iter_src + = __and_<__is_encoded_char<typename _Iter_traits::value_type>, + std::is_base_of<std::input_iterator_tag, + typename _Iter_traits::iterator_category>>; + + template<typename _Iter> + static __is_path_iter_src<_Iter> + __is_path_src(_Iter, int); + + template<typename _CharT, typename _Traits, typename _Alloc> + static __is_encoded_char<_CharT> + __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int); + + template<typename _CharT, typename _Traits> + static __is_encoded_char<_CharT> + __is_path_src(const basic_string_view<_CharT, _Traits>&, int); + + template<typename _Unknown> + static std::false_type + __is_path_src(const _Unknown&, ...); + + template<typename _Tp1, typename _Tp2> + struct __constructible_from; + + template<typename _Iter> + struct __constructible_from<_Iter, _Iter> + : __is_path_iter_src<_Iter> + { }; + + template<typename _Source> + struct __constructible_from<_Source, void> + : decltype(__is_path_src(std::declval<_Source>(), 0)) + { }; + + template<typename _Tp1, typename _Tp2 = void> + using _Path = typename + std::enable_if<__and_<__not_<is_same<_Tp1, path>>, + __constructible_from<_Tp1, _Tp2>>::value, + path>::type; + + template<typename _Source> + static _Source + _S_range_begin(_Source __begin) { return __begin; } + + struct __null_terminated { }; + + template<typename _Source> + static __null_terminated + _S_range_end(_Source) { return {}; } + + template<typename _CharT, typename _Traits, typename _Alloc> + static const _CharT* + _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data(); } + + template<typename _CharT, typename _Traits, typename _Alloc> + static const _CharT* + _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str) + { return __str.data() + __str.size(); } + + template<typename _CharT, typename _Traits> + static const _CharT* + _S_range_begin(const basic_string_view<_CharT, _Traits>& __str) + { return __str.data(); } + + template<typename _CharT, typename _Traits> + static const _CharT* + _S_range_end(const basic_string_view<_CharT, _Traits>& __str) + { return __str.data() + __str.size(); } + + template<typename _Tp, + typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())), + typename _Val = typename std::iterator_traits<_Iter>::value_type> + using __value_type_is_char + = typename std::enable_if<std::is_same<_Val, char>::value>::type; + + public: +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + typedef wchar_t value_type; + static constexpr value_type preferred_separator = L'\\'; +#else + typedef char value_type; + static constexpr value_type preferred_separator = '/'; +#endif + typedef std::basic_string<value_type> string_type; + + enum format { native_format, generic_format, auto_format }; + + // constructors and destructor + + path() noexcept { } + + path(const path& __p) = default; + + path(path&& __p) noexcept + : _M_pathname(std::move(__p._M_pathname)), _M_type(__p._M_type) + { + _M_split_cmpts(); + __p.clear(); + } + + path(string_type&& __source, format = auto_format) + : _M_pathname(std::move(__source)) + { _M_split_cmpts(); } + + template<typename _Source, + typename _Require = _Path<_Source>> + path(_Source const& __source, format = auto_format) + : _M_pathname(_S_convert(_S_range_begin(__source), + _S_range_end(__source))) + { _M_split_cmpts(); } + + template<typename _InputIterator, + typename _Require = _Path<_InputIterator, _InputIterator>> + path(_InputIterator __first, _InputIterator __last, format = auto_format) + : _M_pathname(_S_convert(__first, __last)) + { _M_split_cmpts(); } + + template<typename _Source, + typename _Require = _Path<_Source>, + typename _Require2 = __value_type_is_char<_Source>> + path(_Source const& __source, const locale& __loc, format = auto_format) + : _M_pathname(_S_convert_loc(_S_range_begin(__source), + _S_range_end(__source), __loc)) + { _M_split_cmpts(); } + + template<typename _InputIterator, + typename _Require = _Path<_InputIterator, _InputIterator>, + typename _Require2 = __value_type_is_char<_InputIterator>> + path(_InputIterator __first, _InputIterator __last, const locale& __loc, + format = auto_format) + : _M_pathname(_S_convert_loc(__first, __last, __loc)) + { _M_split_cmpts(); } + + ~path() = default; + + // assignments + + path& operator=(const path& __p) = default; + path& operator=(path&& __p) noexcept; + path& operator=(string_type&& __source); + path& assign(string_type&& __source); + + template<typename _Source> + _Path<_Source>& + operator=(_Source const& __source) + { return *this = path(__source); } + + template<typename _Source> + _Path<_Source>& + assign(_Source const& __source) + { return *this = path(__source); } + + template<typename _InputIterator> + _Path<_InputIterator, _InputIterator>& + assign(_InputIterator __first, _InputIterator __last) + { return *this = path(__first, __last); } + + // appends + + path& operator/=(const path& __p) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + if (__p.is_absolute() + || (__p.has_root_name() && __p.root_name() != root_name())) + operator=(__p); + else + { + string_type __pathname; + if (__p.has_root_directory()) + __pathname = root_name().native(); + else if (has_filename() || (!has_root_directory() && is_absolute())) + __pathname = _M_pathname + preferred_separator; + __pathname += __p.relative_path().native(); // XXX is this right? + _M_pathname.swap(__pathname); + _M_split_cmpts(); + } +#else + // Much simpler, as any path with root-name or root-dir is absolute. + if (__p.is_absolute()) + operator=(__p); + else + { + if (has_filename() || (_M_type == _Type::_Root_name)) + _M_pathname += preferred_separator; + _M_pathname += __p.native(); + _M_split_cmpts(); + } +#endif + return *this; + } + + template <class _Source> + _Path<_Source>& + operator/=(_Source const& __source) + { return append(__source); } + + template<typename _Source> + _Path<_Source>& + append(_Source const& __source) + { + return _M_append(_S_convert(_S_range_begin(__source), + _S_range_end(__source))); + } + + template<typename _InputIterator> + _Path<_InputIterator, _InputIterator>& + append(_InputIterator __first, _InputIterator __last) + { return _M_append(_S_convert(__first, __last)); } + + // concatenation + + path& operator+=(const path& __x); + path& operator+=(const string_type& __x); + path& operator+=(const value_type* __x); + path& operator+=(value_type __x); + path& operator+=(basic_string_view<value_type> __x); + + template<typename _Source> + _Path<_Source>& + operator+=(_Source const& __x) { return concat(__x); } + + template<typename _CharT> + _Path<_CharT*, _CharT*>& + operator+=(_CharT __x); + + template<typename _Source> + _Path<_Source>& + concat(_Source const& __x) + { return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); } + + template<typename _InputIterator> + _Path<_InputIterator, _InputIterator>& + concat(_InputIterator __first, _InputIterator __last) + { return *this += _S_convert(__first, __last); } + + // modifiers + + void clear() noexcept { _M_pathname.clear(); _M_split_cmpts(); } + + path& make_preferred(); + path& remove_filename(); + path& replace_filename(const path& __replacement); + path& replace_extension(const path& __replacement = path()); + + void swap(path& __rhs) noexcept; + + // native format observers + + const string_type& native() const noexcept { return _M_pathname; } + const value_type* c_str() const noexcept { return _M_pathname.c_str(); } + operator string_type() const { return _M_pathname; } + + template<typename _CharT, typename _Traits = std::char_traits<_CharT>, + typename _Allocator = std::allocator<_CharT>> + std::basic_string<_CharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const; + + std::string string() const; +#if _GLIBCXX_USE_WCHAR_T + std::wstring wstring() const; +#endif + std::string u8string() const; + std::u16string u16string() const; + std::u32string u32string() const; + + // generic format observers + template<typename _CharT, typename _Traits = std::char_traits<_CharT>, + typename _Allocator = std::allocator<_CharT>> + std::basic_string<_CharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const; + + std::string generic_string() const; +#if _GLIBCXX_USE_WCHAR_T + std::wstring generic_wstring() const; +#endif + std::string generic_u8string() const; + std::u16string generic_u16string() const; + std::u32string generic_u32string() const; + + // compare + + int compare(const path& __p) const noexcept; + int compare(const string_type& __s) const; + int compare(const value_type* __s) const; + int compare(const basic_string_view<value_type> __s) const; + + // decomposition + + path root_name() const; + path root_directory() const; + path root_path() const; + path relative_path() const; + path parent_path() const; + path filename() const; + path stem() const; + path extension() const; + + // query + + bool empty() const noexcept { return _M_pathname.empty(); } + bool has_root_name() const; + bool has_root_directory() const; + bool has_root_path() const; + bool has_relative_path() const; + bool has_parent_path() const; + bool has_filename() const; + bool has_stem() const; + bool has_extension() const; + bool is_absolute() const; + bool is_relative() const { return !is_absolute(); } + + // generation + path lexically_normal() const; + path lexically_relative(const path& base) const; + path lexically_proximate(const path& base) const; + + // iterators + class iterator; + typedef iterator const_iterator; + + iterator begin() const; + iterator end() const; + + private: + enum class _Type : unsigned char { + _Multi, _Root_name, _Root_dir, _Filename + }; + + path(string_type __str, _Type __type) : _M_pathname(__str), _M_type(__type) + { + __glibcxx_assert(_M_type != _Type::_Multi); + } + + enum class _Split { _Stem, _Extension }; + + path& _M_append(string_type&& __str) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + operator/=(path(std::move(__str))); +#else + if (!_M_pathname.empty() && !_S_is_dir_sep(_M_pathname.back()) + && (__str.empty() || !_S_is_dir_sep(__str.front()))) + _M_pathname += preferred_separator; + _M_pathname += __str; + _M_split_cmpts(); +#endif + return *this; + } + + pair<const string_type*, size_t> _M_find_extension() const; + + template<typename _CharT> + struct _Cvt; + + static string_type + _S_convert(value_type* __src, __null_terminated) + { return string_type(__src); } + + static string_type + _S_convert(const value_type* __src, __null_terminated) + { return string_type(__src); } + + template<typename _Iter> + static string_type + _S_convert(_Iter __first, _Iter __last) + { + using __value_type = typename std::iterator_traits<_Iter>::value_type; + return _Cvt<typename remove_cv<__value_type>::type>:: + _S_convert(__first, __last); + } + + template<typename _InputIterator> + static string_type + _S_convert(_InputIterator __src, __null_terminated) + { + using _Tp = typename std::iterator_traits<_InputIterator>::value_type; + std::basic_string<typename remove_cv<_Tp>::type> __tmp; + for (; *__src != _Tp{}; ++__src) + __tmp.push_back(*__src); + return _S_convert(__tmp.c_str(), __tmp.c_str() + __tmp.size()); + } + + static string_type + _S_convert_loc(const char* __first, const char* __last, + const std::locale& __loc); + + template<typename _Iter> + static string_type + _S_convert_loc(_Iter __first, _Iter __last, const std::locale& __loc) + { + const std::string __str(__first, __last); + return _S_convert_loc(__str.data(), __str.data()+__str.size(), __loc); + } + + template<typename _InputIterator> + static string_type + _S_convert_loc(_InputIterator __src, __null_terminated, + const std::locale& __loc) + { + std::string __tmp; + while (*__src != '\0') + __tmp.push_back(*__src++); + return _S_convert_loc(__tmp.data(), __tmp.data()+__tmp.size(), __loc); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + static basic_string<_CharT, _Traits, _Allocator> + _S_str_convert(const string_type&, const _Allocator& __a); + + bool _S_is_dir_sep(value_type __ch) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return __ch == L'/' || __ch == preferred_separator; +#else + return __ch == '/'; +#endif + } + + void _M_split_cmpts(); + void _M_trim(); + void _M_add_root_name(size_t __n); + void _M_add_root_dir(size_t __pos); + void _M_add_filename(size_t __pos, size_t __n); + + string_type _M_pathname; + + struct _Cmpt; + using _List = _GLIBCXX_STD_C::vector<_Cmpt>; + _List _M_cmpts; // empty unless _M_type == _Type::_Multi + _Type _M_type = _Type::_Multi; + }; + + template<> + struct path::__is_encoded_char<char> : std::true_type + { using value_type = char; }; + + template<> + struct path::__is_encoded_char<wchar_t> : std::true_type + { using value_type = wchar_t; }; + + template<> + struct path::__is_encoded_char<char16_t> : std::true_type + { using value_type = char16_t; }; + + template<> + struct path::__is_encoded_char<char32_t> : std::true_type + { using value_type = char32_t; }; + + template<typename _Tp> + struct path::__is_encoded_char<const _Tp> : __is_encoded_char<_Tp> { }; + + inline void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } + + size_t hash_value(const path& __p) noexcept; + + /// Compare paths + inline bool operator<(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs) < 0; } + + /// Compare paths + inline bool operator<=(const path& __lhs, const path& __rhs) noexcept + { return !(__rhs < __lhs); } + + /// Compare paths + inline bool operator>(const path& __lhs, const path& __rhs) noexcept + { return __rhs < __lhs; } + + /// Compare paths + inline bool operator>=(const path& __lhs, const path& __rhs) noexcept + { return !(__lhs < __rhs); } + + /// Compare paths + inline bool operator==(const path& __lhs, const path& __rhs) noexcept + { return __lhs.compare(__rhs) == 0; } + + /// Compare paths + inline bool operator!=(const path& __lhs, const path& __rhs) noexcept + { return !(__lhs == __rhs); } + + /// Append one path to another + inline path operator/(const path& __lhs, const path& __rhs) + { return path(__lhs) /= __rhs; } + + /// Write a path to a stream + template<typename _CharT, typename _Traits> + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) + { + auto __tmp = __p.string<_CharT, _Traits>(); + using __quoted_string + = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; + __os << __quoted_string{__tmp, '"', '\\'}; + return __os; + } + + /// Read a path from a stream + template<typename _CharT, typename _Traits> + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) + { + basic_string<_CharT, _Traits> __tmp; + using __quoted_string + = std::__detail::_Quoted_string<decltype(__tmp)&, _CharT>; + if (__is >> __quoted_string{ __tmp, '"', '\\' }) + __p = std::move(__tmp); + return __is; + } + + template<typename _Source> + inline auto + u8path(const _Source& __source) + -> decltype(filesystem::path(__source, std::locale::classic())) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + const std::string __u8str{__source}; + return std::filesystem::u8path(__u8str.begin(), __u8str.end()); +#else + return path{ __source }; +#endif + } + + template<typename _InputIterator> + inline auto + u8path(_InputIterator __first, _InputIterator __last) + -> decltype(filesystem::path(__first, __last, std::locale::classic())) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + codecvt_utf8<value_type> __cvt; + string_type __tmp; + if (__str_codecvt_in(__first, __last, __tmp, __cvt)) + return path{ __tmp }; + else + return {}; +#else + return path{ __first, __last }; +#endif + } + + class filesystem_error : public std::system_error + { + public: + filesystem_error(const string& __what_arg, error_code __ec) + : system_error(__ec, __what_arg) { } + + filesystem_error(const string& __what_arg, const path& __p1, + error_code __ec) + : system_error(__ec, __what_arg), _M_path1(__p1) { } + + filesystem_error(const string& __what_arg, const path& __p1, + const path& __p2, error_code __ec) + : system_error(__ec, __what_arg), _M_path1(__p1), _M_path2(__p2) + { } + + ~filesystem_error(); + + const path& path1() const noexcept { return _M_path1; } + const path& path2() const noexcept { return _M_path2; } + const char* what() const noexcept { return _M_what.c_str(); } + + private: + std::string _M_gen_what(); + + path _M_path1; + path _M_path2; + std::string _M_what = _M_gen_what(); + }; + + struct path::_Cmpt : path + { + _Cmpt(string_type __s, _Type __t, size_t __pos) + : path(std::move(__s), __t), _M_pos(__pos) { } + + _Cmpt() : _M_pos(-1) { } + + size_t _M_pos; + }; + + // specialize _Cvt for degenerate 'noconv' case + template<> + struct path::_Cvt<path::value_type> + { + template<typename _Iter> + static string_type + _S_convert(_Iter __first, _Iter __last) + { return string_type{__first, __last}; } + }; + + template<typename _CharT> + struct path::_Cvt + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + static string_type + _S_wconvert(const char* __f, const char* __l, true_type) + { + using _Cvt = std::codecvt<wchar_t, char, mbstate_t>; + const auto& __cvt = std::use_facet<_Cvt>(std::locale{}); + std::wstring __wstr; + if (__str_codecvt_in(__f, __l, __wstr, __cvt)) + return __wstr; + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } + + static string_type + _S_wconvert(const _CharT* __f, const _CharT* __l, false_type) + { + std::codecvt_utf8<_CharT> __cvt; + std::string __str; + if (__str_codecvt_out(__f, __l, __str, __cvt)) + { + const char* __f2 = __str.data(); + const char* __l2 = __f2 + __str.size(); + std::codecvt_utf8<wchar_t> __wcvt; + std::wstring __wstr; + if (__str_codecvt_in(__f2, __l2, __wstr, __wcvt)) + return __wstr; + } + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } + + static string_type + _S_convert(const _CharT* __f, const _CharT* __l) + { + return _S_wconvert(__f, __l, is_same<_CharT, char>{}); + } +#else + static string_type + _S_convert(const _CharT* __f, const _CharT* __l) + { + std::codecvt_utf8<_CharT> __cvt; + std::string __str; + if (__str_codecvt_out(__f, __l, __str, __cvt)) + return __str; + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } +#endif + + static string_type + _S_convert(_CharT* __f, _CharT* __l) + { + return _S_convert(const_cast<const _CharT*>(__f), + const_cast<const _CharT*>(__l)); + } + + template<typename _Iter> + static string_type + _S_convert(_Iter __first, _Iter __last) + { + const std::basic_string<_CharT> __str(__first, __last); + return _S_convert(__str.data(), __str.data() + __str.size()); + } + + template<typename _Iter, typename _Cont> + static string_type + _S_convert(__gnu_cxx::__normal_iterator<_Iter, _Cont> __first, + __gnu_cxx::__normal_iterator<_Iter, _Cont> __last) + { return _S_convert(__first.base(), __last.base()); } + }; + + /// An iterator for the components of a path + class path::iterator + { + public: + using difference_type = std::ptrdiff_t; + using value_type = path; + using reference = const path&; + using pointer = const path*; + using iterator_category = std::bidirectional_iterator_tag; + + iterator() : _M_path(nullptr), _M_cur(), _M_at_end() { } + + iterator(const iterator&) = default; + iterator& operator=(const iterator&) = default; + + reference operator*() const; + pointer operator->() const { return std::__addressof(**this); } + + iterator& operator++(); + iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } + + iterator& operator--(); + iterator operator--(int) { auto __tmp = *this; --*this; return __tmp; } + + friend bool operator==(const iterator& __lhs, const iterator& __rhs) + { return __lhs._M_equals(__rhs); } + + friend bool operator!=(const iterator& __lhs, const iterator& __rhs) + { return !__lhs._M_equals(__rhs); } + + private: + friend class path; + + iterator(const path* __path, path::_List::const_iterator __iter) + : _M_path(__path), _M_cur(__iter), _M_at_end() + { } + + iterator(const path* __path, bool __at_end) + : _M_path(__path), _M_cur(), _M_at_end(__at_end) + { } + + bool _M_equals(iterator) const; + + const path* _M_path; + path::_List::const_iterator _M_cur; + bool _M_at_end; // only used when type != _Multi + }; + + + inline path& + path::operator=(path&& __p) noexcept + { + _M_pathname = std::move(__p._M_pathname); + _M_cmpts = std::move(__p._M_cmpts); + _M_type = __p._M_type; + __p.clear(); + return *this; + } + + inline path& + path::operator=(string_type&& __source) + { return *this = path(std::move(__source)); } + + inline path& + path::assign(string_type&& __source) + { return *this = path(std::move(__source)); } + + inline path& + path::operator+=(const path& __p) + { + return operator+=(__p.native()); + } + + inline path& + path::operator+=(const string_type& __x) + { + _M_pathname += __x; + _M_split_cmpts(); + return *this; + } + + inline path& + path::operator+=(const value_type* __x) + { + _M_pathname += __x; + _M_split_cmpts(); + return *this; + } + + inline path& + path::operator+=(value_type __x) + { + _M_pathname += __x; + _M_split_cmpts(); + return *this; + } + + inline path& + path::operator+=(basic_string_view<value_type> __x) + { + _M_pathname.append(__x.data(), __x.size()); + _M_split_cmpts(); + return *this; + } + + template<typename _CharT> + inline path::_Path<_CharT*, _CharT*>& + path::operator+=(_CharT __x) + { + auto* __addr = std::__addressof(__x); + return concat(__addr, __addr + 1); + } + + inline path& + path::make_preferred() + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + std::replace(_M_pathname.begin(), _M_pathname.end(), L'/', + preferred_separator); +#endif + return *this; + } + + inline void path::swap(path& __rhs) noexcept + { + _M_pathname.swap(__rhs._M_pathname); + _M_cmpts.swap(__rhs._M_cmpts); + std::swap(_M_type, __rhs._M_type); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + std::basic_string<_CharT, _Traits, _Allocator> + path::_S_str_convert(const string_type& __str, const _Allocator& __a) + { + if (__str.size() == 0) + return std::basic_string<_CharT, _Traits, _Allocator>(__a); + + const value_type* __first = __str.data(); + const value_type* __last = __first + __str.size(); + +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + using _CharAlloc = __alloc_rebind<_Allocator, char>; + using _String = basic_string<char, char_traits<char>, _CharAlloc>; + using _WString = basic_string<_CharT, _Traits, _Allocator>; + + // use codecvt_utf8<wchar_t> to convert native string to UTF-8 + codecvt_utf8<value_type> __cvt; + _String __u8str{_CharAlloc{__a}}; + if (__str_codecvt_out(__first, __last, __u8str, __cvt)) + { + if constexpr (is_same_v<_CharT, char>) + return __u8str; + else + { + _WString __wstr; + // use codecvt_utf8<_CharT> to convert UTF-8 to wide string + codecvt_utf8<_CharT> __cvt; + const char* __f = __u8str.data(); + const char* __l = __f + __u8str.size(); + if (__str_codecvt_in(__f, __l, __wstr, __cvt)) + return __wstr; + } + } +#else + codecvt_utf8<_CharT> __cvt; + basic_string<_CharT, _Traits, _Allocator> __wstr{__a}; + if (__str_codecvt_in(__first, __last, __wstr, __cvt)) + return __wstr; +#endif + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline basic_string<_CharT, _Traits, _Allocator> + path::string(const _Allocator& __a) const + { + if constexpr (is_same_v<_CharT, value_type>) +#if _GLIBCXX_USE_CXX11_ABI + return { _M_pathname, __a }; +#else + return { _M_pathname, string_type::size_type(0), __a }; +#endif + else + return _S_str_convert<_CharT, _Traits>(_M_pathname, __a); + } + + inline std::string + path::string() const { return string<char>(); } + +#if _GLIBCXX_USE_WCHAR_T + inline std::wstring + path::wstring() const { return string<wchar_t>(); } +#endif + + inline std::string + path::u8string() const + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + std::string __str; + // convert from native encoding to UTF-8 + codecvt_utf8<value_type> __cvt; + const value_type* __first = _M_pathname.data(); + const value_type* __last = __first + _M_pathname.size(); + if (__str_codecvt_out(__first, __last, __str, __cvt)) + return __str; + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); +#else + return _M_pathname; +#endif + } + + inline std::u16string + path::u16string() const { return string<char16_t>(); } + + inline std::u32string + path::u32string() const { return string<char32_t>(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline std::basic_string<_CharT, _Traits, _Allocator> + path::generic_string(const _Allocator& __a) const + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + const value_type __slash = L'/'; +#else + const value_type __slash = '/'; +#endif + string_type __str(__a); + + if (_M_type == _Type::_Root_dir) + __str.assign(1, __slash); + else + { + __str.reserve(_M_pathname.size()); + bool __add_slash = false; + for (auto& __elem : *this) + { + if (__add_slash) + __str += __slash; + __str += __elem._M_pathname; + __add_slash = __elem._M_type == _Type::_Filename; + } + } + + if constexpr (is_same_v<_CharT, value_type>) + return __str; + else + return _S_str_convert<_CharT, _Traits>(__str, __a); + } + + inline std::string + path::generic_string() const + { return generic_string<char>(); } + +#if _GLIBCXX_USE_WCHAR_T + inline std::wstring + path::generic_wstring() const + { return generic_string<wchar_t>(); } +#endif + + inline std::string + path::generic_u8string() const + { return generic_string(); } + + inline std::u16string + path::generic_u16string() const + { return generic_string<char16_t>(); } + + inline std::u32string + path::generic_u32string() const + { return generic_string<char32_t>(); } + + inline int + path::compare(const string_type& __s) const { return compare(path(__s)); } + + inline int + path::compare(const value_type* __s) const { return compare(path(__s)); } + + inline int + path::compare(basic_string_view<value_type> __s) const + { return compare(path(__s)); } + + inline path + path::filename() const + { + if (empty()) + return {}; + else if (_M_type == _Type::_Filename) + return *this; + else if (_M_type == _Type::_Multi) + { + if (_M_pathname.back() == preferred_separator) + return {}; + auto& __last = *--end(); + if (__last._M_type == _Type::_Filename) + return __last; + } + return {}; + } + + inline path + path::stem() const + { + auto ext = _M_find_extension(); + if (ext.first && ext.second != 0) + return path{ext.first->substr(0, ext.second)}; + return {}; + } + + inline path + path::extension() const + { + auto ext = _M_find_extension(); + if (ext.first && ext.second != string_type::npos) + return path{ext.first->substr(ext.second)}; + return {}; + } + + inline bool + path::has_stem() const + { + auto ext = _M_find_extension(); + return ext.first && ext.second != 0; + } + + inline bool + path::has_extension() const + { + auto ext = _M_find_extension(); + return ext.first && ext.second != string_type::npos; + } + + inline bool + path::is_absolute() const + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return has_root_name(); +#else + return has_root_directory(); +#endif + } + + inline path::iterator + path::begin() const + { + if (_M_type == _Type::_Multi) + return iterator(this, _M_cmpts.begin()); + return iterator(this, false); + } + + inline path::iterator + path::end() const + { + if (_M_type == _Type::_Multi) + return iterator(this, _M_cmpts.end()); + return iterator(this, true); + } + + inline path::iterator& + path::iterator::operator++() + { + __glibcxx_assert(_M_path != nullptr); + if (_M_path->_M_type == _Type::_Multi) + { + __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); + ++_M_cur; + } + else + { + __glibcxx_assert(!_M_at_end); + _M_at_end = true; + } + return *this; + } + + inline path::iterator& + path::iterator::operator--() + { + __glibcxx_assert(_M_path != nullptr); + if (_M_path->_M_type == _Type::_Multi) + { + __glibcxx_assert(_M_cur != _M_path->_M_cmpts.begin()); + --_M_cur; + } + else + { + __glibcxx_assert(_M_at_end); + _M_at_end = false; + } + return *this; + } + + inline path::iterator::reference + path::iterator::operator*() const + { + __glibcxx_assert(_M_path != nullptr); + if (_M_path->_M_type == _Type::_Multi) + { + __glibcxx_assert(_M_cur != _M_path->_M_cmpts.end()); + return *_M_cur; + } + return *_M_path; + } + + inline bool + path::iterator::_M_equals(iterator __rhs) const + { + if (_M_path != __rhs._M_path) + return false; + if (_M_path == nullptr) + return true; + if (_M_path->_M_type == path::_Type::_Multi) + return _M_cur == __rhs._M_cur; + return _M_at_end == __rhs._M_at_end; + } + + // @} group filesystem +_GLIBCXX_END_NAMESPACE_CXX11 +} // namespace filesystem + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_FS_PATH_H diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h index da6d49c96c4..e19f92abd76 100644 --- a/libstdc++-v3/include/bits/hashtable_policy.h +++ b/libstdc++-v3/include/bits/hashtable_policy.h @@ -31,7 +31,9 @@ #ifndef _HASHTABLE_POLICY_H #define _HASHTABLE_POLICY_H 1 -#include <bits/stl_algobase.h> // for std::min. +#include <tuple> // for std::tuple, std::forward_as_tuple +#include <cstdint> // for std::uint_fast64_t +#include <bits/stl_algobase.h> // for std::min. namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/bits/node_handle.h b/libstdc++-v3/include/bits/node_handle.h index c7694a1e0ef..4a830630c89 100644 --- a/libstdc++-v3/include/bits/node_handle.h +++ b/libstdc++-v3/include/bits/node_handle.h @@ -37,7 +37,6 @@ # define __cpp_lib_node_extract 201606 #include <optional> -#include <tuple> #include <bits/alloc_traits.h> #include <bits/ptr_traits.h> @@ -283,26 +282,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Iterator position = _Iterator(); bool inserted = false; _NodeHandle node; - - template<size_t _Idx> - decltype(auto) get() & - { return std::get<_Idx>(std::tie(inserted, position, node)); } - - template<size_t _Idx> - decltype(auto) get() const & - { return std::get<_Idx>(std::tie(inserted, position, node)); } - - template<size_t _Idx> - decltype(auto) get() && - { - return std::move(std::get<_Idx>(std::tie(inserted, position, node))); - } - - template<size_t _Idx> - decltype(auto) get() const && - { - return std::move(std::get<_Idx>(std::tie(inserted, position, node))); - } }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/specfun.h b/libstdc++-v3/include/bits/specfun.h index 0aaebeab7ac..6bb3ec09681 100644 --- a/libstdc++-v3/include/bits/specfun.h +++ b/libstdc++-v3/include/bits/specfun.h @@ -1201,6 +1201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION } // namespace std +#ifndef __STRICT_ANSI__ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -1305,6 +1306,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION } // namespace __gnu_cxx +#endif // __STRICT_ANSI__ #pragma GCC visibility pop diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index ea413b1b155..b5facef55dd 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -180,7 +180,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _InputIterator __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) { - for (; __len; --__len, ++__first) + for (; __len; --__len, (void) ++__first) if (!__pred(__first)) break; return __first; @@ -4462,7 +4462,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __typeof__(__gen())>) for (__decltype(__n + 0) __niter = __n; - __niter > 0; --__niter, ++__first) + __niter > 0; --__niter, (void) ++__first) *__first = __gen(); return __first; } diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index a80934c4faa..bfdfc7ded5e 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -738,7 +738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value) { for (__decltype(__n + 0) __niter = __n; - __niter > 0; --__niter, ++__first) + __niter > 0; --__niter, (void) ++__first) *__first = __value; return __first; } @@ -750,7 +750,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { const _Tp __tmp = __value; for (__decltype(__n + 0) __niter = __n; - __niter > 0; --__niter, ++__first) + __niter > 0; --__niter, (void) ++__first) *__first = __tmp; return __first; } @@ -796,7 +796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static bool equal(_II1 __first1, _II1 __last1, _II2 __first2) { - for (; __first1 != __last1; ++__first1, (void)++__first2) + for (; __first1 != __last1; ++__first1, (void) ++__first2) if (!(*__first1 == *__first2)) return false; return true; diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index d24e760d01b..ac548846b0e 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -417,7 +417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__last._M_offset != 0) __fill_bvector(__last._M_p, 0, __last._M_offset, __x); } - else + else if (__first._M_offset != __last._M_offset) __fill_bvector(__first._M_p, __first._M_offset, __last._M_offset, __x); } diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 88667a568c3..74ef0d9bf88 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1244,6 +1244,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter) #endif // C++11 +#if __cpp_deduction_guides >= 201606 + // These helper traits are used for deduction guides + // of associative containers. + template<typename _InputIterator> + using __iter_key_t = remove_const_t< + typename iterator_traits<_InputIterator>::value_type::first_type>; + + template<typename _InputIterator> + using __iter_val_t = + typename iterator_traits<_InputIterator>::value_type::second_type; + + template<typename _T1, typename _T2> + struct pair; + + template<typename _InputIterator> + using __iter_to_alloc_t = + pair<add_const_t<__iter_key_t<_InputIterator>>, + __iter_val_t<_InputIterator>>; + +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index 0e8a98a96c1..8a9e6c9c329 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -778,7 +778,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Attempts to insert a std::pair into the %map. - * @param __x Pair to be inserted (see std::make_pair for easy * creation of pairs). * @@ -791,12 +790,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * first element (the key) is not already present in the %map. * * Insertion requires logarithmic time. + * @{ */ std::pair<iterator, bool> insert(const value_type& __x) { return _M_t._M_insert_unique(__x); } #if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + std::pair<iterator, bool> + insert(value_type&& __x) + { return _M_t._M_insert_unique(std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -804,6 +810,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(_Pair&& __x) { return _M_t._M_insert_unique(std::forward<_Pair>(__x)); } #endif + // @} #if __cplusplus >= 201103L /** @@ -840,6 +847,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * for more on @a hinting. * * Insertion requires logarithmic time (if the hint is not taken). + * @{ */ iterator #if __cplusplus >= 201103L @@ -850,6 +858,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_t._M_insert_unique_(__position, __x); } #if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_unique_(__position, std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -858,6 +872,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_t._M_insert_unique_(__position, std::forward<_Pair>(__x)); } #endif + // @} /** * @brief Template function that attempts to insert a range of elements. @@ -1366,6 +1381,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const map<_K1, _T1, _C1, _A1>&); }; + +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = less<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template<typename _Key, typename _Tp, typename _Compare = less<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + map(initializer_list<pair<_Key, _Tp>>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<_Key, _Tp, _Compare, _Allocator>; + + template <typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, _Allocator) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + map(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> map<_Key, _Tp, less<_Key>, _Allocator>; + +#endif + /** * @brief Map equality comparison. * @param __x A %map. diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index 7e3cea48a47..1a16bf982e3 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -526,12 +526,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * thus multiple pairs with the same key can be inserted. * * Insertion requires logarithmic time. + * @{ */ iterator insert(const value_type& __x) { return _M_t._M_insert_equal(__x); } #if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(value_type&& __x) + { return _M_t._M_insert_equal(std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -539,6 +546,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(_Pair&& __x) { return _M_t._M_insert_equal(std::forward<_Pair>(__x)); } #endif + // @} /** * @brief Inserts a std::pair into the %multimap. @@ -559,6 +567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints * * Insertion requires logarithmic time (if the hint is not taken). + * @{ */ iterator #if __cplusplus >= 201103L @@ -569,6 +578,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_t._M_insert_equal_(__position, __x); } #if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_equal_(__position, std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -577,6 +592,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { return _M_t._M_insert_equal_(__position, std::forward<_Pair>(__x)); } #endif + // @} /** * @brief A template function that attempts to insert a range @@ -1031,6 +1047,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const multimap<_K1, _T1, _C1, _A1>&); }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = less<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template<typename _Key, typename _Tp, typename _Compare = less<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + multimap(initializer_list<pair<_Key, _Tp>>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<_Key, _Tp, _Compare, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, _Allocator) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> multimap<_Key, _Tp, less<_Key>, _Allocator>; + +#endif + /** * @brief Multimap equality comparison. * @param __x A %multimap. diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index 517e77e9372..d34b6758e18 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -881,6 +881,43 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const multiset<_K1, _C1, _A1>&); }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = + less<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<typename iterator_traits<_InputIterator>::value_type, + _Compare, _Allocator>; + + template<typename _Key, + typename _Compare = less<_Key>, + typename _Allocator = allocator<_Key>, + typename = _RequireAllocator<_Allocator>> + multiset(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<_Key, _Compare, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, _Allocator) + -> multiset<typename iterator_traits<_InputIterator>::value_type, + less<typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Key, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + multiset(initializer_list<_Key>, _Allocator) + -> multiset<_Key, less<_Key>, _Allocator>; + +#endif + /** * @brief Multiset equality comparison. * @param __x A %multiset. @@ -971,6 +1008,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) { return __set._M_t; } }; + #endif // C++17 _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index e804a7cae70..3a7992c4dab 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -898,6 +898,41 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator<(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = + less<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set<typename iterator_traits<_InputIterator>::value_type, + _Compare, _Allocator>; + + template<typename _Key, typename _Compare = less<_Key>, + typename _Allocator = allocator<_Key>, + typename = _RequireAllocator<_Allocator>> + set(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set<_Key, _Compare, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, _Allocator) + -> set<typename iterator_traits<_InputIterator>::value_type, + less<typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Key, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + set(initializer_list<_Key>, _Allocator) + -> set<_Key, less<_Key>, _Allocator>; + +#endif /** * @brief Set equality comparison. diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index c2ba863ed98..bac3fd01f7a 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -206,7 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __cur = __first; __try { - for (; __n > 0; --__n, ++__cur) + for (; __n > 0; --__n, (void) ++__cur) std::_Construct(std::__addressof(*__cur), __x); return __cur; } @@ -347,7 +347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __try { typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __n > 0; --__n, ++__cur) + for (; __n > 0; --__n, (void) ++__cur) __traits::construct(__alloc, std::__addressof(*__cur), __x); return __cur; } @@ -523,7 +523,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __cur = __first; __try { - for (; __n > 0; --__n, ++__cur) + for (; __n > 0; --__n, (void) ++__cur) std::_Construct(std::__addressof(*__cur)); return __cur; } @@ -627,7 +627,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __try { typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __n > 0; --__n, ++__cur) + for (; __n > 0; --__n, (void) ++__cur) __traits::construct(__alloc, std::__addressof(*__cur)); return __cur; } @@ -687,7 +687,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __cur = __first; __try { - for (; __n > 0; --__n, ++__cur) + for (; __n > 0; --__n, (void) ++__cur) std::_Construct_novalue(std::__addressof(*__cur)); return __cur; } @@ -747,7 +747,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __cur = __result; __try { - for (; __n > 0; --__n, ++__first, ++__cur) + for (; __n > 0; --__n, (void) ++__first, ++__cur) std::_Construct(std::__addressof(*__cur), *__first); return __cur; } @@ -775,7 +775,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __cur = __result; __try { - for (; __n > 0; --__n, ++__first, ++__cur) + for (; __n > 0; --__n, (void) ++__first, ++__cur) std::_Construct(std::__addressof(*__cur), *__first); return {__first, __cur}; } diff --git a/libstdc++-v3/include/bits/string_view.tcc b/libstdc++-v3/include/bits/string_view.tcc index 4d98f8668a0..5c53c584381 100644 --- a/libstdc++-v3/include/bits/string_view.tcc +++ b/libstdc++-v3/include/bits/string_view.tcc @@ -119,7 +119,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits> constexpr typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>:: - find_first_of(const _CharT* __str, size_type __pos, size_type __n) const + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept { __glibcxx_requires_string_len(__str, __n); for (; __n && __pos < this->_M_len; ++__pos) @@ -135,7 +136,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits> constexpr typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>:: - find_last_of(const _CharT* __str, size_type __pos, size_type __n) const + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept { __glibcxx_requires_string_len(__str, __n); size_type __size = this->size(); @@ -156,7 +158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits> constexpr typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>:: - find_first_not_of(const _CharT* __str, size_type __pos, size_type __n) const + find_first_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept { __glibcxx_requires_string_len(__str, __n); for (; __pos < this->_M_len; ++__pos) @@ -179,7 +182,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits> constexpr typename basic_string_view<_CharT, _Traits>::size_type basic_string_view<_CharT, _Traits>:: - find_last_not_of(const _CharT* __str, size_type __pos, size_type __n) const + find_last_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept { __glibcxx_requires_string_len(__str, __n); size_type __size = this->_M_len; diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index df1302c80c0..385e4bd4df4 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -579,6 +579,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(const value_type& __x) { return _M_h.insert(__x); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + std::pair<iterator, bool> + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -613,6 +619,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(const_iterator __hint, const value_type& __x) { return _M_h.insert(__hint, __x); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -1118,6 +1130,82 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&); }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = hash<__iter_key_t<_InputIterator>>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + _Hash, _Pred, _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, + typename unordered_map<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map<int, int>::size_type, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map<int, int>::size_type, + _Hash, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, + typename unordered_map<int, int>::size_type, + _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, + typename unordered_map<int, int>::size_type, + _Hash, _Allocator) + -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + /** * @brief A standard container composed of equivalent keys * (possibly containing multiple of each key value) that associates @@ -1468,6 +1556,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(const value_type& __x) { return _M_h.insert(__x); } + iterator + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -1500,6 +1592,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(const_iterator __hint, const value_type& __x) { return _M_h.insert(__hint, __x); } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + template<typename _Pair, typename = typename std::enable_if<std::is_constructible<value_type, _Pair&&>::value>::type> @@ -1871,6 +1969,82 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Hash1, _Pred1, _Alloc1>&); }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = hash<__iter_key_t<_InputIterator>>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, _Pred, + _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, + unordered_multimap<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap<int, int>::size_type, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap<int, int>::size_type, _Hash, + _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, + unordered_multimap<int, int>::size_type, + _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, + unordered_multimap<int, int>::size_type, + _Hash, _Allocator) + -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> inline void swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index df57915f31a..416dbbcfb96 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -805,6 +805,70 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&); }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = + hash<typename iterator_traits<_InputIterator>::value_type>, + typename _Pred = + equal_to<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<typename iterator_traits<_InputIterator>::value_type, + _Hash, _Pred, _Allocator>; + + template<typename _Tp, typename _Hash = hash<_Tp>, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set<int>::size_type, _Allocator) + -> unordered_set<typename iterator_traits<_InputIterator>::value_type, + hash< + typename iterator_traits<_InputIterator>::value_type>, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set<int>::size_type, + _Hash, _Allocator) + -> unordered_set<typename iterator_traits<_InputIterator>::value_type, + _Hash, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set<int>::size_type, _Allocator) + -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template<typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set<int>::size_type, _Hash, _Allocator) + -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + /** * @brief A standard container composed of equivalent keys * (possibly containing multiple of each key value) in which the @@ -1517,6 +1581,75 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&); }; + +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = + hash<typename iterator_traits<_InputIterator>::value_type>, + typename _Pred = + equal_to<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, + _Hash, _Pred, _Allocator>; + + template<typename _Tp, typename _Hash = hash<_Tp>, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset<int>::size_type, _Allocator) + -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, + hash<typename + iterator_traits<_InputIterator>::value_type>, + equal_to<typename + iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset<int>::size_type, + _Hash, _Allocator) + -> unordered_multiset<typename + iterator_traits<_InputIterator>::value_type, + _Hash, + equal_to< + typename + iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset<int>::size_type, _Allocator) + -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template<typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset<int>::size_type, _Hash, _Allocator) + -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + template<class _Value, class _Hash, class _Pred, class _Alloc> inline void swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, diff --git a/libstdc++-v3/include/c_compatibility/math.h b/libstdc++-v3/include/c_compatibility/math.h index 84755c8c35c..28c7c8368f0 100644 --- a/libstdc++-v3/include/c_compatibility/math.h +++ b/libstdc++-v3/include/c_compatibility/math.h @@ -111,7 +111,7 @@ using std::tgamma; using std::trunc; #endif // C++11 && _GLIBCXX_USE_C99_MATH_TR1 -#if __STDCPP_WANT_MATH_SPEC_FUNCS__ == 1 +#if _GLIBCXX_USE_STD_SPEC_FUNCS using std::assoc_laguerref; using std::assoc_laguerrel; using std::assoc_laguerre; @@ -175,7 +175,7 @@ using std::sph_legendre; using std::sph_neumannf; using std::sph_neumannl; using std::sph_neumann; -#endif // __STDCPP_WANT_MATH_SPEC_FUNCS__ +#endif // _GLIBCXX_USE_STD_SPEC_FUNCS #endif // _GLIBCXX_MATH_H #endif // __cplusplus diff --git a/libstdc++-v3/include/c_global/cstddef b/libstdc++-v3/include/c_global/cstddef index 09754ee45da..11d268b7f81 100644 --- a/libstdc++-v3/include/c_global/cstddef +++ b/libstdc++-v3/include/c_global/cstddef @@ -57,9 +57,11 @@ namespace std } #endif -#if __cplusplus > 201402L +#if __cplusplus >= 201703L namespace std { +#define __cpp_lib_byte 201603 + /// std::byte enum class byte : unsigned char {}; diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array index 9c279221040..95edc84f38b 100644 --- a/libstdc++-v3/include/debug/array +++ b/libstdc++-v3/include/debug/array @@ -306,6 +306,14 @@ namespace __debug return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: _S_ref(__arr._M_elems, _Int); } + + template<std::size_t _Int, typename _Tp, std::size_t _Nm> + constexpr const _Tp&& + get(const array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "index is out of bounds"); + return std::move(__debug::get<_Int>(__arr)); + } } // namespace __debug _GLIBCXX_BEGIN_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 7e3c193c103..5816b4b1624 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -624,6 +624,16 @@ namespace __debug _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; +#if __cpp_deduction_guides >= 201606 + template<typename _InputIterator, typename _ValT + = typename iterator_traits<_InputIterator>::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + deque(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> deque<_ValT, _Allocator>; +#endif + template<typename _Tp, typename _Alloc> inline bool operator==(const deque<_Tp, _Alloc>& __lhs, diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index cd343302b00..20c7ebe4a8f 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -772,6 +772,16 @@ namespace __debug _M_base() const noexcept { return *this; } }; +#if __cpp_deduction_guides >= 201606 + template<typename _InputIterator, typename _ValT + = typename iterator_traits<_InputIterator>::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + forward_list(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> forward_list<_ValT, _Allocator>; +#endif + template<typename _Tp, typename _Alloc> bool operator==(const forward_list<_Tp, _Alloc>& __lx, diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list index a45ece244bd..94d325c6e6a 100644 --- a/libstdc++-v3/include/debug/list +++ b/libstdc++-v3/include/debug/list @@ -769,6 +769,16 @@ namespace __debug _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; +#if __cpp_deduction_guides >= 201606 + template<typename _InputIterator, typename _ValT + = typename iterator_traits<_InputIterator>::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + list(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> list<_ValT, _Allocator>; +#endif + template<typename _Tp, typename _Alloc> inline bool operator==(const list<_Tp, _Alloc>& __lhs, diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h index c275979052c..d5a2c9f6e6f 100644 --- a/libstdc++-v3/include/debug/map.h +++ b/libstdc++-v3/include/debug/map.h @@ -667,6 +667,39 @@ namespace __debug _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = less<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template<typename _Key, typename _Tp, typename _Compare = less<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + map(initializer_list<pair<_Key, _Tp>>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<_Key, _Tp, _Compare, _Allocator>; + + template <typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, _Allocator) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + map(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> map<_Key, _Tp, less<_Key>, _Allocator>; + +#endif + template<typename _Key, typename _Tp, typename _Compare, typename _Allocator> inline bool diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index f971cfa41f0..6c7b2ab4f8d 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -555,6 +555,39 @@ namespace __debug _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = less<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template<typename _Key, typename _Tp, typename _Compare = less<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + multimap(initializer_list<pair<_Key, _Tp>>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<_Key, _Tp, _Compare, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, _Allocator) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> multimap<_Key, _Tp, less<_Key>, _Allocator>; + +#endif + template<typename _Key, typename _Tp, typename _Compare, typename _Allocator> inline bool diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h index 97c7b843f27..59331b4bc6b 100644 --- a/libstdc++-v3/include/debug/multiset.h +++ b/libstdc++-v3/include/debug/multiset.h @@ -542,6 +542,43 @@ namespace __debug _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = + less<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<typename iterator_traits<_InputIterator>::value_type, + _Compare, _Allocator>; + + template<typename _Key, + typename _Compare = less<_Key>, + typename _Allocator = allocator<_Key>, + typename = _RequireAllocator<_Allocator>> + multiset(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<_Key, _Compare, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, _Allocator) + -> multiset<typename iterator_traits<_InputIterator>::value_type, + less<typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Key, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + multiset(initializer_list<_Key>, _Allocator) + -> multiset<_Key, less<_Key>, _Allocator>; + +#endif + template<typename _Key, typename _Compare, typename _Allocator> inline bool operator==(const multiset<_Key, _Compare, _Allocator>& __lhs, diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h index 07032865bc9..5353cfe87b2 100644 --- a/libstdc++-v3/include/debug/set.h +++ b/libstdc++-v3/include/debug/set.h @@ -560,6 +560,42 @@ namespace __debug _M_base() const _GLIBCXX_NOEXCEPT { return *this; } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Compare = + less<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set<typename iterator_traits<_InputIterator>::value_type, + _Compare, _Allocator>; + + template<typename _Key, typename _Compare = less<_Key>, + typename _Allocator = allocator<_Key>, + typename = _RequireAllocator<_Allocator>> + set(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set<_Key, _Compare, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, _Allocator) + -> set<typename iterator_traits<_InputIterator>::value_type, + less<typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Key, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + set(initializer_list<_Key>, _Allocator) + -> set<_Key, less<_Key>, _Allocator>; + +#endif + template<typename _Key, typename _Compare, typename _Allocator> inline bool operator==(const set<_Key, _Compare, _Allocator>& __lhs, diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map index 51a55ae21f3..c5734304846 100644 --- a/libstdc++-v3/include/debug/unordered_map +++ b/libstdc++-v3/include/debug/unordered_map @@ -616,6 +616,82 @@ namespace __debug } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = hash<__iter_key_t<_InputIterator>>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + _Hash, _Pred, _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, + typename unordered_map<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map<int, int>::size_type, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map<int, int>::size_type, + _Hash, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, + typename unordered_map<int, int>::size_type, + _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list<pair<_Key, _Tp>>, + typename unordered_map<int, int>::size_type, + _Hash, _Allocator) + -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + template<typename _Key, typename _Tp, typename _Hash, typename _Pred, typename _Alloc> inline void @@ -1110,6 +1186,82 @@ namespace __debug } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = hash<__iter_key_t<_InputIterator>>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, _Pred, + _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash = hash<_Key>, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator<pair<const _Key, _Tp>>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, + unordered_multimap<int, int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap<int, int>::size_type, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap<int, int>::size_type, _Hash, + _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, + unordered_multimap<int, int>::size_type, + _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template<typename _Key, typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list<pair<_Key, _Tp>>, + unordered_multimap<int, int>::size_type, + _Hash, _Allocator) + -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + template<typename _Key, typename _Tp, typename _Hash, typename _Pred, typename _Alloc> inline void diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set index 923ff2bc4d8..1fe493fe52f 100644 --- a/libstdc++-v3/include/debug/unordered_set +++ b/libstdc++-v3/include/debug/unordered_set @@ -530,6 +530,70 @@ namespace __debug } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = + hash<typename iterator_traits<_InputIterator>::value_type>, + typename _Pred = + equal_to<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<typename iterator_traits<_InputIterator>::value_type, + _Hash, _Pred, _Allocator>; + + template<typename _Tp, typename _Hash = hash<_Tp>, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set<int>::size_type, _Allocator) + -> unordered_set<typename iterator_traits<_InputIterator>::value_type, + hash< + typename iterator_traits<_InputIterator>::value_type>, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set<int>::size_type, + _Hash, _Allocator) + -> unordered_set<typename iterator_traits<_InputIterator>::value_type, + _Hash, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set<int>::size_type, _Allocator) + -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template<typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set<int>::size_type, _Hash, _Allocator) + -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> inline void swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, @@ -1012,6 +1076,74 @@ namespace __debug } }; +#if __cpp_deduction_guides >= 201606 + + template<typename _InputIterator, + typename _Hash = + hash<typename iterator_traits<_InputIterator>::value_type>, + typename _Pred = + equal_to<typename iterator_traits<_InputIterator>::value_type>, + typename _Allocator = + allocator<typename iterator_traits<_InputIterator>::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, + _Hash, _Pred, _Allocator>; + + template<typename _Tp, typename _Hash = hash<_Tp>, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset<int>::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; + + template<typename _InputIterator, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset<int>::size_type, _Allocator) + -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, + hash<typename + iterator_traits<_InputIterator>::value_type>, + equal_to<typename + iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _InputIterator, typename _Hash, typename _Allocator, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset<int>::size_type, + _Hash, _Allocator) + -> unordered_multiset<typename + iterator_traits<_InputIterator>::value_type, + _Hash, + equal_to< + typename + iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template<typename _Tp, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset<int>::size_type, _Allocator) + -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template<typename _Tp, typename _Hash, typename _Allocator, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset<int>::size_type, _Hash, _Allocator) + -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> inline void swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector index a6d18d94508..c24c2f3d45f 100644 --- a/libstdc++-v3/include/debug/vector +++ b/libstdc++-v3/include/debug/vector @@ -757,6 +757,16 @@ namespace __debug _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs))) { __lhs.swap(__rhs); } +#if __cpp_deduction_guides >= 201606 + template<typename _InputIterator, typename _ValT + = typename iterator_traits<_InputIterator>::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + vector(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> vector<_ValT, _Allocator>; +#endif + } // namespace __debug #if __cplusplus >= 201103L diff --git a/libstdc++-v3/include/experimental/bits/fs_dir.h b/libstdc++-v3/include/experimental/bits/fs_dir.h index 1ff0d9b6def..ecadf37a9cd 100644 --- a/libstdc++-v3/include/experimental/bits/fs_dir.h +++ b/libstdc++-v3/include/experimental/bits/fs_dir.h @@ -49,7 +49,7 @@ namespace filesystem inline namespace v1 { /** - * @ingroup filesystem + * @ingroup filesystem-ts * @{ */ @@ -351,7 +351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_END_NAMESPACE_CXX11 - // @} group filesystem + // @} group filesystem-ts } // namespace v1 } // namespace filesystem } // namespace experimental diff --git a/libstdc++-v3/include/experimental/bits/fs_fwd.h b/libstdc++-v3/include/experimental/bits/fs_fwd.h index 7b851a3d4a8..ac43c5f44f5 100644 --- a/libstdc++-v3/include/experimental/bits/fs_fwd.h +++ b/libstdc++-v3/include/experimental/bits/fs_fwd.h @@ -53,7 +53,7 @@ inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } #endif /** - * @defgroup filesystem Filesystem + * @defgroup filesystem-ts Filesystem TS * @ingroup experimental * * Utilities for performing operations on file systems and their components, @@ -278,7 +278,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 bool is_regular_file(file_status) noexcept; bool is_symlink(file_status) noexcept; - // @} group filesystem + // @} group filesystem-ts } // namespace v1 } // namespace filesystem } // namespace experimental diff --git a/libstdc++-v3/include/experimental/bits/fs_ops.h b/libstdc++-v3/include/experimental/bits/fs_ops.h index 387537260e0..fa7f1de6bc4 100644 --- a/libstdc++-v3/include/experimental/bits/fs_ops.h +++ b/libstdc++-v3/include/experimental/bits/fs_ops.h @@ -47,7 +47,7 @@ namespace filesystem inline namespace v1 { /** - * @ingroup filesystem + * @ingroup filesystem-ts * @{ */ @@ -285,7 +285,7 @@ inline namespace v1 path temp_directory_path(); path temp_directory_path(error_code& __ec); - // @} group filesystem + // @} group filesystem-ts } // namespace v1 } // namespace filesystem } // namespace experimental diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index cde3897b8e5..3e9bc6357af 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -72,7 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #endif /** - * @ingroup filesystem + * @ingroup filesystem-ts * @{ */ @@ -725,10 +725,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 pointer operator->() const { return std::__addressof(**this); } iterator& operator++(); - iterator operator++(int) { auto __tmp = *this; ++_M_cur; return __tmp; } + iterator operator++(int) { auto __tmp = *this; ++*this; return __tmp; } iterator& operator--(); - iterator operator--(int) { auto __tmp = *this; --_M_cur; return __tmp; } + iterator operator--(int) { auto __tmp = *this; --*this; return __tmp; } friend bool operator==(const iterator& __lhs, const iterator& __rhs) { return __lhs._M_equals(__rhs); } @@ -1079,7 +1079,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return _M_at_end == __rhs._M_at_end; } - // @} group filesystem + // @} group filesystem-ts _GLIBCXX_END_NAMESPACE_CXX11 } // namespace v1 } // namespace filesystem diff --git a/libstdc++-v3/include/experimental/filesystem b/libstdc++-v3/include/experimental/filesystem index f0b19dd2910..90f6f9eabfe 100644 --- a/libstdc++-v3/include/experimental/filesystem +++ b/libstdc++-v3/include/experimental/filesystem @@ -40,36 +40,6 @@ #define __cpp_lib_experimental_filesystem 201406 -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace experimental -{ -namespace filesystem -{ -inline namespace v1 -{ - /** - * @ingroup filesystem - */ - inline std::string filesystem_error::_M_gen_what() - { - std::string __what = "filesystem error: "; - __what += system_error::what(); - if (!_M_path1.empty()) - __what += " [" + _M_path1.string() + ']'; - if (!_M_path2.empty()) - __what += " [" + _M_path2.string() + ']'; - return __what; - } -} // namespace v1 -} // namespace filesystem -} // namespace experimental - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - #endif // C++11 #endif // _GLIBCXX_EXPERIMENTAL_FILESYSTEM diff --git a/libstdc++-v3/include/experimental/string_view b/libstdc++-v3/include/experimental/string_view index f05f152302a..8eaf9ec3d96 100644 --- a/libstdc++-v3/include/experimental/string_view +++ b/libstdc++-v3/include/experimental/string_view @@ -645,22 +645,22 @@ namespace experimental inline namespace string_view_literals { inline constexpr basic_string_view<char> - operator""sv(const char* __str, size_t __len) + operator""sv(const char* __str, size_t __len) noexcept { return basic_string_view<char>{__str, __len}; } #ifdef _GLIBCXX_USE_WCHAR_T inline constexpr basic_string_view<wchar_t> - operator""sv(const wchar_t* __str, size_t __len) + operator""sv(const wchar_t* __str, size_t __len) noexcept { return basic_string_view<wchar_t>{__str, __len}; } #endif #ifdef _GLIBCXX_USE_C99_STDINT_TR1 inline constexpr basic_string_view<char16_t> - operator""sv(const char16_t* __str, size_t __len) + operator""sv(const char16_t* __str, size_t __len) noexcept { return basic_string_view<char16_t>{__str, __len}; } inline constexpr basic_string_view<char32_t> - operator""sv(const char32_t* __str, size_t __len) + operator""sv(const char32_t* __str, size_t __len) noexcept { return basic_string_view<char32_t>{__str, __len}; } #endif } // namespace string_literals diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h index b2993cd379f..4e1a71afeb0 100644 --- a/libstdc++-v3/include/precompiled/stdc++.h +++ b/libstdc++-v3/include/precompiled/stdc++.h @@ -122,6 +122,7 @@ #include <shared_mutex> #endif -#if __cplusplus > 201402L +#if __cplusplus >= 201703L #include <charconv> +#include <filesystem> #endif diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array index 1c7d6dc4ab1..01f7100bae0 100644 --- a/libstdc++-v3/include/std/array +++ b/libstdc++-v3/include/std/array @@ -328,6 +328,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _S_ref(__arr._M_elems, _Int); } + template<std::size_t _Int, typename _Tp, std::size_t _Nm> + constexpr const _Tp&& + get(const array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); + } + _GLIBCXX_END_NAMESPACE_CONTAINER } // namespace std @@ -339,7 +347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// tuple_size template<typename _Tp> - class tuple_size; + struct tuple_size; /// Partial specialization for std::array template<typename _Tp, std::size_t _Nm> @@ -348,7 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// tuple_element template<std::size_t _Int, typename _Tp> - class tuple_element; + struct tuple_element; /// Partial specialization for std::array template<std::size_t _Int, typename _Tp, std::size_t _Nm> diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index fc058fcd8d8..9491508e637 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -214,8 +214,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION treat_as_floating_point<_Rep>::value; #endif // C++17 -#if __cplusplus > 201402L -# define __cpp_lib_chrono 201510 +#if __cplusplus >= 201703L +# define __cpp_lib_chrono 201611 template<typename _ToDur, typename _Rep, typename _Period> constexpr __enable_if_is_duration<_ToDur> diff --git a/libstdc++-v3/include/std/filesystem b/libstdc++-v3/include/std/filesystem new file mode 100644 index 00000000000..b09997704c1 --- /dev/null +++ b/libstdc++-v3/include/std/filesystem @@ -0,0 +1,45 @@ +// <filesystem> -*- C++ -*- + +// Copyright (C) 2014-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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file filesystem + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_FILESYSTEM +#define _GLIBCXX_FILESYSTEM 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include <bits/fs_fwd.h> +#include <bits/fs_path.h> +#include <bits/fs_dir.h> +#include <bits/fs_ops.h> + +#define __cpp_lib_filesystem 201703 + +#endif // C++17 + +#endif // _GLIBCXX_FILESYSTEM diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream index 52830945fe2..a3324c004d7 100644 --- a/libstdc++-v3/include/std/fstream +++ b/libstdc++-v3/include/std/fstream @@ -216,6 +216,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } +#if __cplusplus >= 201703L + template<typename _Path, typename _Result = _Path, typename _Path2 + = decltype(std::declval<_Path&>().make_preferred().native())> + using _If_path = enable_if_t<is_same_v<_Path, _Path2>, _Result>; +#endif // C++17 + public: // Constructors/destructor: /** @@ -306,7 +312,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __filebuf_type* open(const std::string& __s, ios_base::openmode __mode) { return open(__s.c_str(), __mode); } -#endif + +#if __cplusplus >= 201703L + /** + * @brief Opens an external file. + * @param __s The name of the file, as a filesystem::path. + * @param __mode The open mode flags. + * @return @c this on success, NULL on failure + */ + template<typename _Path> + _If_path<_Path, __filebuf_type*> + open(const _Path& __s, ios_base::openmode __mode) + { return open(__s.c_str(), __mode); } +#endif // C++17 +#endif // C++11 /** * @brief Closes the currently associated file. @@ -487,9 +506,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __mode Open file in specified mode (see std::ios_base). * * @c ios_base::in is automatically included in @a __mode. - * - * Tip: When using std::string to hold the filename, you must use - * .c_str() before passing it to this constructor. */ explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in) @@ -516,13 +532,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION this->open(__s, __mode); } +#if __cplusplus >= 201703L + /** + * @param Create an input file stream. + * @param __s filesystem::path specifying the filename. + * @param __mode Open file in specified mode (see std::ios_base). + * + * @c ios_base::in is automatically included in @a __mode. + */ + template<typename _Path, typename = _Require< + is_constructible<__filebuf_type, const _Path&, ios_base::openmode>>> + basic_ifstream(const _Path& __s, + ios_base::openmode __mode = ios_base::in) + : basic_ifstream(__s.c_str(), __mode) + { } +#endif // C++17 + basic_ifstream(const basic_ifstream&) = delete; basic_ifstream(basic_ifstream&& __rhs) : __istream_type(std::move(__rhs)), _M_filebuf(std::move(__rhs._M_filebuf)) { __istream_type::set_rdbuf(&_M_filebuf); } -#endif +#endif // C++11 /** * @brief The destructor does nothing. @@ -587,9 +619,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Calls @c std::basic_filebuf::open(s,__mode|in). If that function * fails, @c failbit is set in the stream's error state. - * - * Tip: When using std::string to hold the filename, you must use - * .c_str() before passing it to this constructor. */ void open(const char* __s, ios_base::openmode __mode = ios_base::in) @@ -621,7 +650,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 409. Closing an fstream should clear error state this->clear(); } -#endif + +#if __cplusplus >= 201703L + /** + * @brief Opens an external file. + * @param __s The name of the file, as a filesystem::path. + * @param __mode The open mode flags. + * + * Calls @c std::basic_filebuf::open(__s,__mode|in). If that function + * fails, @c failbit is set in the stream's error state. + */ + template<typename _Path> + auto + open(const _Path& __s, ios_base::openmode __mode = ios_base::in) + -> decltype(_M_filebuf.open(__s, __mode)) + { open(__s.c_str(), __mode); } +#endif // C++17 +#endif // C++11 /** * @brief Close the file. @@ -687,15 +732,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __s Null terminated string specifying the filename. * @param __mode Open file in specified mode (see std::ios_base). * - * @c ios_base::out | @c ios_base::trunc is automatically included in - * @a __mode. - * - * Tip: When using std::string to hold the filename, you must use - * .c_str() before passing it to this constructor. + * @c ios_base::out is automatically included in @a __mode. */ explicit basic_ofstream(const char* __s, - ios_base::openmode __mode = ios_base::out|ios_base::trunc) + ios_base::openmode __mode = ios_base::out) : __ostream_type(), _M_filebuf() { this->init(&_M_filebuf); @@ -708,18 +749,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __s std::string specifying the filename. * @param __mode Open file in specified mode (see std::ios_base). * - * @c ios_base::out | @c ios_base::trunc is automatically included in - * @a __mode. + * @c ios_base::out is automatically included in @a __mode. */ explicit basic_ofstream(const std::string& __s, - ios_base::openmode __mode = ios_base::out|ios_base::trunc) + ios_base::openmode __mode = ios_base::out) : __ostream_type(), _M_filebuf() { this->init(&_M_filebuf); this->open(__s, __mode); } +#if __cplusplus >= 201703L + /** + * @param Create an output file stream. + * @param __s filesystem::path specifying the filename. + * @param __mode Open file in specified mode (see std::ios_base). + * + * @c ios_base::out is automatically included in @a __mode. + */ + template<typename _Path, typename = _Require< + is_constructible<__filebuf_type, const _Path&, ios_base::openmode>>> + basic_ofstream(const _Path& __s, + ios_base::openmode __mode = ios_base::out) + : basic_ofstream(__s.c_str(), __mode) + { } +#endif // C++17 + basic_ofstream(const basic_ofstream&) = delete; basic_ofstream(basic_ofstream&& __rhs) @@ -789,15 +845,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __s The name of the file. * @param __mode The open mode flags. * - * Calls @c std::basic_filebuf::open(__s,__mode|out|trunc). If that + * Calls @c std::basic_filebuf::open(__s,__mode|out). If that * function fails, @c failbit is set in the stream's error state. - * - * Tip: When using std::string to hold the filename, you must use - * .c_str() before passing it to this constructor. */ void - open(const char* __s, - ios_base::openmode __mode = ios_base::out | ios_base::trunc) + open(const char* __s, ios_base::openmode __mode = ios_base::out) { if (!_M_filebuf.open(__s, __mode | ios_base::out)) this->setstate(ios_base::failbit); @@ -813,12 +865,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __s The name of the file. * @param __mode The open mode flags. * - * Calls @c std::basic_filebuf::open(s,mode|out|trunc). If that + * Calls @c std::basic_filebuf::open(s,mode|out). If that * function fails, @c failbit is set in the stream's error state. */ void - open(const std::string& __s, - ios_base::openmode __mode = ios_base::out | ios_base::trunc) + open(const std::string& __s, ios_base::openmode __mode = ios_base::out) { if (!_M_filebuf.open(__s, __mode | ios_base::out)) this->setstate(ios_base::failbit); @@ -827,7 +878,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 409. Closing an fstream should clear error state this->clear(); } -#endif + +#if __cplusplus >= 201703L + /** + * @brief Opens an external file. + * @param __s The name of the file, as a filesystem::path. + * @param __mode The open mode flags. + * + * Calls @c std::basic_filebuf::open(__s,__mode|out). If that + * function fails, @c failbit is set in the stream's error state. + */ + template<typename _Path> + auto + open(const _Path& __s, ios_base::openmode __mode = ios_base::out) + -> decltype(_M_filebuf.open(__s, __mode)) + { open(__s.c_str(), __mode); } +#endif // C++17 +#endif // C++11 /** * @brief Close the file. @@ -894,9 +961,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @brief Create an input/output file stream. * @param __s Null terminated string specifying the filename. * @param __mode Open file in specified mode (see std::ios_base). - * - * Tip: When using std::string to hold the filename, you must use - * .c_str() before passing it to this constructor. */ explicit basic_fstream(const char* __s, @@ -922,6 +986,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION this->open(__s, __mode); } +#if __cplusplus >= 201703L + /** + * @param Create an input/output file stream. + * @param __s filesystem::path specifying the filename. + * @param __mode Open file in specified mode (see std::ios_base). + */ + template<typename _Path, typename = _Require< + is_constructible<__filebuf_type, const _Path&, ios_base::openmode>>> + basic_fstream(const _Path& __s, + ios_base::openmode __mode = ios_base::in | ios_base::out) + : basic_fstream(__s.c_str(), __mode) + { } +#endif // C++17 + basic_fstream(const basic_fstream&) = delete; basic_fstream(basic_fstream&& __rhs) @@ -993,9 +1071,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * Calls @c std::basic_filebuf::open(__s,__mode). If that * function fails, @c failbit is set in the stream's error state. - * - * Tip: When using std::string to hold the filename, you must use - * .c_str() before passing it to this constructor. */ void open(const char* __s, @@ -1029,7 +1104,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 409. Closing an fstream should clear error state this->clear(); } -#endif + +#if __cplusplus >= 201703L + /** + * @brief Opens an external file. + * @param __s The name of the file, as a filesystem::path. + * @param __mode The open mode flags. + * + * Calls @c std::basic_filebuf::open(__s,__mode). If that + * function fails, @c failbit is set in the stream's error state. + */ + template<typename _Path> + auto + open(const _Path& __s, + ios_base::openmode __mode = ios_base::in | ios_base::out) + -> decltype(_M_filebuf.open(__s, __mode)) + { open(__s.c_str(), __mode); } +#endif // C++17 +#endif // C++11 /** * @brief Close the file. diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex index 8c692a88ffd..50420ee22d4 100644 --- a/libstdc++-v3/include/std/mutex +++ b/libstdc++-v3/include/std/mutex @@ -688,6 +688,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __set_once_functor_lock_ptr(0); #endif +#ifdef __clang_analyzer__ + // PR libstdc++/82481 + __once_callable = nullptr; + __once_call = nullptr; +#endif + if (__e) __throw_system_error(__e); } diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index 97316ef49ab..1900b867841 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -96,14 +96,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr basic_string_view(const basic_string_view&) noexcept = default; - constexpr basic_string_view(const _CharT* __str) + constexpr basic_string_view(const _CharT* __str) noexcept : _M_len{__str == nullptr ? 0 : traits_type::length(__str)}, _M_str{__str} { } - constexpr basic_string_view(const _CharT* __str, size_type __len) - : _M_len{__len}, - _M_str{__str} + constexpr + basic_string_view(const _CharT* __str, size_type __len) noexcept + : _M_len{__len}, _M_str{__str} { } constexpr basic_string_view& @@ -177,17 +177,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr const _CharT& at(size_type __pos) const { - return __pos < this->_M_len - ? *(this->_M_str + __pos) - : (__throw_out_of_range_fmt(__N("basic_string_view::at: __pos " - "(which is %zu) >= this->size() " - "(which is %zu)"), - __pos, this->size()), - *this->_M_str); + if (__pos >= _M_len) + __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " + "(which is %zu) >= this->size() " + "(which is %zu)"), __pos, this->size()); + return *(this->_M_str + __pos); } constexpr const _CharT& - front() const + front() const noexcept { // TODO: Assert to restore in a way compatible with the constexpr. // __glibcxx_assert(this->_M_len > 0); @@ -195,7 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } constexpr const _CharT& - back() const + back() const noexcept { // TODO: Assert to restore in a way compatible with the constexpr. // __glibcxx_assert(this->_M_len > 0); @@ -209,7 +207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [string.view.modifiers], modifiers: constexpr void - remove_prefix(size_type __n) + remove_prefix(size_type __n) noexcept { __glibcxx_assert(this->_M_len >= __n); this->_M_str += __n; @@ -217,7 +215,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } constexpr void - remove_suffix(size_type __n) + remove_suffix(size_type __n) noexcept { this->_M_len -= __n; } constexpr void @@ -235,38 +233,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION copy(_CharT* __str, size_type __n, size_type __pos = 0) const { __glibcxx_requires_string_len(__str, __n); - if (__pos > this->_M_len) - __throw_out_of_range_fmt(__N("basic_string_view::copy: __pos " - "(which is %zu) > this->size() " - "(which is %zu)"), - __pos, this->size()); - size_type __rlen{std::min(__n, size_type{this->_M_len - __pos})}; + __pos = _M_check(__pos, "basic_string_view::copy"); + const size_type __rlen = std::min(__n, _M_len - __pos); for (auto __begin = this->_M_str + __pos, __end = __begin + __rlen; __begin != __end;) *__str++ = *__begin++; return __rlen; } - - // [string.view.ops], string operations: - constexpr basic_string_view - substr(size_type __pos, size_type __n=npos) const + substr(size_type __pos, size_type __n = npos) const noexcept(false) { - return __pos <= this->_M_len - ? basic_string_view{this->_M_str + __pos, - std::min(__n, size_type{this->_M_len - __pos})} - : (__throw_out_of_range_fmt(__N("basic_string_view::substr: __pos " - "(which is %zu) > this->size() " - "(which is %zu)"), - __pos, this->size()), basic_string_view{}); + __pos = _M_check(__pos, "basic_string_view::substr"); + const size_type __rlen = std::min(__n, _M_len - __pos); + return basic_string_view{_M_str + __pos, __rlen}; } constexpr int compare(basic_string_view __str) const noexcept { - int __ret = traits_type::compare(this->_M_str, __str._M_str, - std::min(this->_M_len, __str._M_len)); + const size_type __rlen = std::min(this->_M_len, __str._M_len); + int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); if (__ret == 0) __ret = _S_compare(this->_M_len, __str._M_len); return __ret; @@ -279,7 +266,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __str, size_type __pos2, size_type __n2) const - { return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); } + { + return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); + } constexpr int compare(const _CharT* __str) const noexcept @@ -291,7 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr int compare(size_type __pos1, size_type __n1, - const _CharT* __str, size_type __n2) const + const _CharT* __str, size_type __n2) const noexcept(false) { return this->substr(__pos1, __n1) .compare(basic_string_view(__str, __n2)); @@ -302,13 +291,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return this->find(__str._M_str, __pos, __str._M_len); } constexpr size_type - find(_CharT __c, size_type __pos=0) const noexcept; + find(_CharT __c, size_type __pos = 0) const noexcept; constexpr size_type find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; constexpr size_type - find(const _CharT* __str, size_type __pos=0) const noexcept + find(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find(__str, __pos, traits_type::length(__str)); } constexpr size_type @@ -350,7 +339,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return this->rfind(__c, __pos); } constexpr size_type - find_last_of(const _CharT* __str, size_type __pos, size_type __n) const; + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; constexpr size_type find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept @@ -366,7 +356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr size_type find_first_not_of(const _CharT* __str, - size_type __pos, size_type __n) const; + size_type __pos, size_type __n) const noexcept; constexpr size_type find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept @@ -385,7 +375,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr size_type find_last_not_of(const _CharT* __str, - size_type __pos, size_type __n) const; + size_type __pos, size_type __n) const noexcept; constexpr size_type find_last_not_of(const _CharT* __str, @@ -396,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } constexpr size_type - _M_check(size_type __pos, const char* __s) const + _M_check(size_type __pos, const char* __s) const noexcept(false) { if (__pos > this->size()) __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > " @@ -407,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // NB: _M_limit doesn't check for a bad __pos value. constexpr size_type - _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT + _M_limit(size_type __pos, size_type __off) const noexcept { const bool __testoff = __off < this->size() - __pos; return __testoff ? __off : this->size() - __pos; @@ -418,11 +408,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr int _S_compare(size_type __n1, size_type __n2) noexcept { - return difference_type{__n1 - __n2} > std::numeric_limits<int>::max() - ? std::numeric_limits<int>::max() - : difference_type{__n1 - __n2} < std::numeric_limits<int>::min() - ? std::numeric_limits<int>::min() - : static_cast<int>(difference_type{__n1 - __n2}); + const difference_type __diff{__n1 - __n2}; + if (__diff > std::numeric_limits<int>::max()) + return std::numeric_limits<int>::max(); + if (__diff < std::numeric_limits<int>::min()) + return std::numeric_limits<int>::min(); + return static_cast<int>(__diff); } size_t _M_len; @@ -636,22 +627,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline namespace string_view_literals { inline constexpr basic_string_view<char> - operator""sv(const char* __str, size_t __len) + operator""sv(const char* __str, size_t __len) noexcept { return basic_string_view<char>{__str, __len}; } #ifdef _GLIBCXX_USE_WCHAR_T inline constexpr basic_string_view<wchar_t> - operator""sv(const wchar_t* __str, size_t __len) + operator""sv(const wchar_t* __str, size_t __len) noexcept { return basic_string_view<wchar_t>{__str, __len}; } #endif #ifdef _GLIBCXX_USE_C99_STDINT_TR1 inline constexpr basic_string_view<char16_t> - operator""sv(const char16_t* __str, size_t __len) + operator""sv(const char16_t* __str, size_t __len) noexcept { return basic_string_view<char16_t>{__str, __len}; } inline constexpr basic_string_view<char32_t> - operator""sv(const char32_t* __str, size_t __len) + operator""sv(const char32_t* __str, size_t __len) noexcept { return basic_string_view<char32_t>{__str, __len}; } #endif } // namespace string_literals diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 1f5365ad026..ac03c9ec402 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -1329,6 +1329,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::forward<__element_type&&>(std::get<__i>(__t)); } + /// Return a const rvalue reference to the ith element of a const tuple rvalue. + template<std::size_t __i, typename... _Elements> + constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& + get(const tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward<const __element_type&&>(std::get<__i>(__t)); + } + #if __cplusplus > 201103L #define __cpp_lib_tuples_by_type 201304 @@ -1360,6 +1369,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr const _Tp& get(const tuple<_Types...>& __t) noexcept { return std::__get_helper2<_Tp>(__t); } + + /// Return a const reference to the unique element of type _Tp of + /// a const tuple rvalue. + template <typename _Tp, typename... _Types> + constexpr const _Tp&& + get(const tuple<_Types...>&& __t) noexcept + { return std::forward<const _Tp&&>(std::__get_helper2<_Tp>(__t)); } #endif // This class performs the comparison operations on tuples diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 036f7667bd8..7eca08c1a50 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2664,7 +2664,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void operator=(__nonesuch const&) = delete; }; -#if __cplusplus > 201402L +#if __cplusplus >= 201703L # define __cpp_lib_is_invocable 201703 /// std::invoke_result @@ -2739,7 +2739,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = is_nothrow_invocable_r<_Fn, _Args...>::value; #endif // C++17 -#if __cplusplus > 201402L +#if __cplusplus >= 201703L # define __cpp_lib_type_trait_variable_templates 201510L template <typename _Tp> inline constexpr bool is_void_v = is_void<_Tp>::value; @@ -2943,6 +2943,16 @@ template <typename _From, typename _To> #endif // C++17 +#if __cplusplus > 201703L + /// Byte order + enum class endian + { + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__ + }; +#endif // C++2a + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map index 2cdcd377936..80773235b65 100644 --- a/libstdc++-v3/include/std/unordered_map +++ b/libstdc++-v3/include/std/unordered_map @@ -35,13 +35,12 @@ # include <bits/c++0x_warning.h> #else -#include <utility> #include <type_traits> #include <initializer_list> -#include <tuple> #include <bits/allocator.h> #include <ext/alloc_traits.h> #include <ext/aligned_buffer.h> +#include <bits/stl_pair.h> #include <bits/stl_function.h> // equal_to, _Identity, _Select1st #include <bits/functional_hash.h> #include <bits/hashtable.h> diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set index 2646c0f2f00..faf7ebe23ae 100644 --- a/libstdc++-v3/include/std/unordered_set +++ b/libstdc++-v3/include/std/unordered_set @@ -35,13 +35,12 @@ # include <bits/c++0x_warning.h> #else -#include <utility> #include <type_traits> #include <initializer_list> -#include <tuple> #include <bits/allocator.h> #include <ext/alloc_traits.h> #include <ext/aligned_buffer.h> +#include <bits/stl_pair.h> #include <bits/stl_function.h> // equal_to, _Identity, _Select1st #include <bits/functional_hash.h> #include <bits/hashtable.h> diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 29a626004f9..e7386320e2a 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -184,6 +184,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr const _Tp1& __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept { return __pair.first; } + + template<typename _Tp1, typename _Tp2> + static constexpr const _Tp1&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<const _Tp1>(__pair.first); } }; template<> @@ -203,6 +208,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr const _Tp2& __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept { return __pair.second; } + + template<typename _Tp1, typename _Tp2> + static constexpr const _Tp2&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<const _Tp2>(__pair.second); } }; template<std::size_t _Int, class _Tp1, class _Tp2> @@ -220,6 +230,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION get(const std::pair<_Tp1, _Tp2>& __in) noexcept { return __pair_get<_Int>::__const_get(__in); } + template<std::size_t _Int, class _Tp1, class _Tp2> + constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& + get(const std::pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__const_move_get(std::move(__in)); } + #if __cplusplus > 201103L #define __cpp_lib_tuples_by_type 201304 @@ -240,6 +255,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return std::move(__p.first); } template <typename _Tp, typename _Up> + constexpr const _Tp&& + get(const pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template <typename _Tp, typename _Up> constexpr _Tp& get(pair<_Up, _Tp>& __p) noexcept { return __p.second; } @@ -254,6 +274,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION get(pair<_Up, _Tp>&& __p) noexcept { return std::move(__p.second); } + template <typename _Tp, typename _Up> + constexpr const _Tp&& + get(const pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + #define __cpp_lib_exchange_function 201304 /// Assign @p __new_val to @p __obj and return its previous value. |