| // { dg-do run { target c++17 } } |
| // { dg-require-effective-target std_allocator_new } |
| // { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } } |
| |
| // Copyright (C) 2021-2023 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| // libstdc++/96088 |
| |
| #include <string_view> |
| #include <string> |
| #include <unordered_set> |
| #include <vector> |
| |
| #include <testsuite_hooks.h> |
| #include <replacement_memory_operators.h> |
| |
| static constexpr std::initializer_list<const char*> lst = { |
| "long_str_for_dynamic_allocating" |
| }; |
| |
| void |
| test01() |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string> us; |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 4 ); |
| } |
| |
| void |
| test02() |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string, |
| std::hash<std::string_view>, |
| std::equal_to<std::string_view>> us; |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| } |
| |
| std::size_t |
| hash_string_f(const std::string& str) noexcept |
| { |
| std::hash<std::string> h; |
| return h(str); |
| } |
| |
| void |
| test11() |
| { |
| typedef std::size_t (*hash_string_t)(const std::string&) noexcept; |
| __gnu_test::counter::reset(); |
| hash_string_t hasher = &hash_string_f; |
| std::unordered_set<std::string, |
| hash_string_t, |
| std::equal_to<std::string>> us(0, hasher); |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 4 ); |
| } |
| |
| std::size_t |
| hash_string_view_f(const std::string_view& str) noexcept |
| { |
| std::hash<std::string_view> h; |
| return h(str); |
| } |
| |
| void |
| test12() |
| { |
| typedef std::size_t (*hash_stringview_t)(const std::string_view&) noexcept; |
| __gnu_test::counter::reset(); |
| hash_stringview_t hasher = &hash_string_view_f; |
| std::unordered_set<std::string, |
| hash_stringview_t, |
| std::equal_to<std::string_view>> us(0, hasher); |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| } |
| |
| struct hash_string_functor |
| { |
| std::size_t |
| operator()(const std::string& str) const noexcept |
| { |
| std::hash<std::string> h; |
| return h(str); |
| } |
| }; |
| |
| void |
| test21() |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string, |
| hash_string_functor, |
| std::equal_to<std::string>> us; |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 4 ); |
| } |
| |
| struct hash_string_view_noexcept_functor |
| { |
| std::size_t |
| operator()(const std::string_view& str) const noexcept |
| { |
| std::hash<std::string_view> h; |
| return h(str); |
| } |
| }; |
| |
| void |
| test22() |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string, |
| hash_string_view_noexcept_functor, |
| std::equal_to<std::string_view>> us; |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| } |
| |
| struct hash_string_view_functor |
| { |
| std::size_t |
| operator()(const std::string_view& str) const |
| { |
| std::hash<std::string_view> h; |
| return h(str); |
| } |
| }; |
| |
| void |
| test23() |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string, |
| hash_string_view_functor, |
| std::equal_to<std::string_view>> us; |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| |
| us.insert(lst.begin(), lst.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == 3 ); |
| VERIFY( __gnu_test::counter::get()._M_increments == 3 ); |
| } |
| |
| void |
| test03() |
| { |
| std::vector<std::string> v; |
| v.insert(v.end(), lst.begin(), lst.end()); |
| |
| const auto origin = __gnu_test::counter::count(); |
| |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string, |
| std::hash<std::string_view>, |
| std::equal_to<std::string_view>> us; |
| us.insert(v.begin(), v.end()); |
| VERIFY( us.size() == 1 ); |
| |
| // Allocate array of buckets, a node, and the std::string (unless COW). |
| constexpr std::size_t increments = _GLIBCXX_USE_CXX11_ABI ? 3 : 2; |
| |
| VERIFY( __gnu_test::counter::count() == origin + increments ); |
| VERIFY( __gnu_test::counter::get()._M_increments == increments ); |
| |
| us.insert(v.begin(), v.end()); |
| VERIFY( us.size() == 1 ); |
| |
| VERIFY( __gnu_test::counter::count() == origin + increments ); |
| VERIFY( __gnu_test::counter::get()._M_increments == increments ); |
| } |
| VERIFY( __gnu_test::counter::count() == origin ); |
| |
| { |
| __gnu_test::counter::reset(); |
| std::unordered_set<std::string, |
| std::hash<std::string_view>, |
| std::equal_to<std::string_view>> us; |
| us.insert(std::make_move_iterator(v.begin()), |
| std::make_move_iterator(v.end())); |
| VERIFY( us.size() == 1 ); |
| |
| // Allocate array of buckets and a node. String is moved. |
| constexpr std::size_t increments = 2; |
| |
| VERIFY( __gnu_test::counter::count() == origin + increments ); |
| VERIFY( __gnu_test::counter::get()._M_increments == increments ); |
| } |
| } |
| |
| int |
| main() |
| { |
| test01(); |
| test02(); |
| test11(); |
| test12(); |
| test21(); |
| test22(); |
| test23(); |
| test03(); |
| return 0; |
| } |