From 4f5847e189860a9cddf4aa018917f7a1009e0747 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 2 Sep 2022 13:32:00 +0100 Subject: [PATCH] Updates for unordered maps and sets for an API that better matches the STL --- include/etl/unordered_map.h | 11 +-- include/etl/unordered_multimap.h | 44 ++++++------ include/etl/unordered_multiset.h | 45 ++++++------ include/etl/unordered_set.h | 41 +++++------ test/test_unordered_map.cpp | 117 ++++++++++++++++++++++++++++++- test/test_unordered_multimap.cpp | 109 ++++++++++++++++++++++++++++ test/test_unordered_multiset.cpp | 99 ++++++++++++++++++++++++++ test/test_unordered_set.cpp | 100 ++++++++++++++++++++++++++ 8 files changed, 490 insertions(+), 76 deletions(-) diff --git a/include/etl/unordered_map.h b/include/etl/unordered_map.h index 4eac7c92..cf52b692 100644 --- a/include/etl/unordered_map.h +++ b/include/etl/unordered_map.h @@ -1294,6 +1294,7 @@ namespace etl // Skip if doing self assignment if (this != &rhs) { + clear(); key_hash_function = rhs.hash_function(); key_equal_function = rhs.key_eq(); this->move(rhs.begin(), rhs.end()); @@ -1534,7 +1535,7 @@ namespace etl //************************************************************************* /// Default constructor. //************************************************************************* - unordered_map(const THash& hash = THash(), const TKeyEqual equal = TKeyEqual()) + unordered_map(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) : base(node_pool, buckets, MAX_BUCKETS_, hash, equal) { } @@ -1569,8 +1570,8 @@ namespace etl ///\param last The iterator to the last element + 1. //************************************************************************* template - unordered_map(TIterator first_, TIterator last_) - : unordered_map() + unordered_map(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS_, hash, equal) { base::assign(first_, last_); } @@ -1579,8 +1580,8 @@ namespace etl //************************************************************************* /// Construct from initializer_list. //************************************************************************* - unordered_map(std::initializer_list> init) - : unordered_map() + unordered_map(std::initializer_list> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS_, hash, equal) { base::assign(init.begin(), init.end()); } diff --git a/include/etl/unordered_multimap.h b/include/etl/unordered_multimap.h index 9f5131ca..69aba453 100644 --- a/include/etl/unordered_multimap.h +++ b/include/etl/unordered_multimap.h @@ -678,7 +678,7 @@ namespace etl while (inode != bucket.end()) { // Do we already have this key? - if (inode->key_value_pair.first == key) + if (key_equal_function(inode->key_value_pair.first, key)) { break; } @@ -747,7 +747,7 @@ namespace etl while (inode != bucket.end()) { // Do we already have this key? - if (inode->key_value_pair.first == key) + if (key_equal_function(inode->key_value_pair.first, key)) { break; } @@ -831,7 +831,7 @@ namespace etl while (icurrent != bucket.end()) { - if (icurrent->key_value_pair.first == key) + if (key_equal_function(icurrent->key_value_pair.first, key)) { bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key_value_pair.~value_type(); // Destroy the value. @@ -1184,6 +1184,8 @@ namespace etl // Skip if doing self assignment if (this != &rhs) { + key_hash_function = rhs.hash_function(); + key_equal_function = rhs.key_eq(); assign(rhs.cbegin(), rhs.cend()); } @@ -1199,6 +1201,9 @@ namespace etl // Skip if doing self assignment if (this != &rhs) { + clear(); + key_hash_function = rhs.hash_function(); + key_equal_function = rhs.key_eq(); move(rhs.begin(), rhs.end()); } @@ -1211,12 +1216,14 @@ namespace etl //********************************************************************* /// Constructor. //********************************************************************* - iunordered_multimap(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_) + iunordered_multimap(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_) : pnodepool(&node_pool_) , pbuckets(pbuckets_) , number_of_buckets(number_of_buckets_) , first(pbuckets) , last(pbuckets) + , key_hash_function(key_hash_function_) + , key_equal_function(key_equal_function_) { } @@ -1434,8 +1441,8 @@ namespace etl //************************************************************************* /// Default constructor. //************************************************************************* - unordered_multimap() - : base(node_pool, buckets, MAX_BUCKETS) + unordered_multimap(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { } @@ -1443,7 +1450,7 @@ namespace etl /// Copy constructor. //************************************************************************* unordered_multimap(const unordered_multimap& other) - : base(node_pool, buckets, MAX_BUCKETS) + : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq()) { // Skip if doing self assignment if (this != &other) @@ -1457,7 +1464,7 @@ namespace etl /// Move constructor. //************************************************************************* unordered_multimap(unordered_multimap&& other) - : base(node_pool, buckets, MAX_BUCKETS) + : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq()) { // Skip if doing self assignment if (this != &other) @@ -1474,8 +1481,8 @@ namespace etl ///\param last The iterator to the last element + 1. //************************************************************************* template - unordered_multimap(TIterator first_, TIterator last_) - : base(node_pool, buckets, MAX_BUCKETS) + unordered_multimap(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { base::assign(first_, last_); } @@ -1484,8 +1491,8 @@ namespace etl //************************************************************************* /// Construct from initializer_list. //************************************************************************* - unordered_multimap(std::initializer_list> init) - : base(node_pool, buckets, MAX_BUCKETS_) + unordered_multimap(std::initializer_list> init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS_, hash, equal) { base::assign(init.begin(), init.end()); } @@ -1504,11 +1511,7 @@ namespace etl //************************************************************************* unordered_multimap& operator = (const unordered_multimap& rhs) { - // Skip if doing self assignment - if (this != &rhs) - { - base::assign(rhs.cbegin(), rhs.cend()); - } + base::operator=(rhs); return *this; } @@ -1519,12 +1522,7 @@ namespace etl //************************************************************************* unordered_multimap& operator = (unordered_multimap&& rhs) { - // Skip if doing self assignment - if (this != &rhs) - { - base::clear(); - base::move(rhs.begin(), rhs.end()); - } + base::operator=(etl::move(rhs)); return *this; } diff --git a/include/etl/unordered_multiset.h b/include/etl/unordered_multiset.h index 6fba7d13..260151c7 100644 --- a/include/etl/unordered_multiset.h +++ b/include/etl/unordered_multiset.h @@ -673,7 +673,7 @@ namespace etl while (inode != bucket.end()) { // Do we already have this key? - if (inode->key == key) + if (key_equal_function(inode->key, key)) { break; } @@ -742,7 +742,7 @@ namespace etl while (inode != bucket.end()) { // Do we already have this key? - if (inode->key == key) + if (key_equal_function(inode->key, key)) { break; } @@ -814,7 +814,7 @@ namespace etl while (icurrent != bucket.end()) { - if (icurrent->key == key) + if (key_equal_function(icurrent->key, key)) { bucket.erase_after(iprevious); // Unlink from the bucket. icurrent->key.~value_type(); // Destroy the value. @@ -1167,6 +1167,8 @@ namespace etl // Skip if doing self assignment if (this != &rhs) { + key_hash_function = rhs.hash_function(); + key_equal_function = rhs.key_eq(); assign(rhs.cbegin(), rhs.cend()); } @@ -1183,6 +1185,8 @@ namespace etl if (this != &rhs) { clear(); + key_hash_function = rhs.hash_function(); + key_equal_function = rhs.key_eq(); move(rhs.begin(), rhs.end()); } @@ -1195,12 +1199,14 @@ namespace etl //********************************************************************* /// Constructor. //********************************************************************* - iunordered_multiset(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_) + iunordered_multiset(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_) : pnodepool(&node_pool_) , pbuckets(pbuckets_) , number_of_buckets(number_of_buckets_) , first(pbuckets) , last(pbuckets) + , key_hash_function(key_hash_function_) + , key_equal_function(key_equal_function_) { } @@ -1412,15 +1418,15 @@ namespace etl public: - static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_; + static ETL_CONSTANT size_t MAX_SIZE = MAX_SIZE_; static ETL_CONSTANT size_t MAX_BUCKETS = MAX_BUCKETS_; //************************************************************************* /// Default constructor. //************************************************************************* - unordered_multiset() - : base(node_pool, buckets, MAX_BUCKETS) + unordered_multiset(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { } @@ -1428,7 +1434,7 @@ namespace etl /// Copy constructor. //************************************************************************* unordered_multiset(const unordered_multiset& other) - : base(node_pool, buckets, MAX_BUCKETS) + : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq()) { // Skip if doing self assignment if (this != &other) @@ -1443,7 +1449,7 @@ namespace etl /// Move constructor. //************************************************************************* unordered_multiset(unordered_multiset&& other) - : base(node_pool, buckets, MAX_BUCKETS) + : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq()) { // Skip if doing self assignment if (this != &other) @@ -1460,8 +1466,8 @@ namespace etl ///\param last The iterator to the last element + 1. //************************************************************************* template - unordered_multiset(TIterator first_, TIterator last_) - : base(node_pool, buckets, MAX_BUCKETS) + unordered_multiset(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { base::assign(first_, last_); } @@ -1470,8 +1476,8 @@ namespace etl //************************************************************************* /// Construct from initializer_list. //************************************************************************* - unordered_multiset(std::initializer_list init) - : base(node_pool, buckets, MAX_BUCKETS) + unordered_multiset(std::initializer_list init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { base::assign(init.begin(), init.end()); } @@ -1490,11 +1496,7 @@ namespace etl //************************************************************************* unordered_multiset& operator = (const unordered_multiset& rhs) { - // Skip if doing self assignment - if (this != &rhs) - { - base::assign(rhs.cbegin(), rhs.cend()); - } + base::operator =(rhs); return *this; } @@ -1505,12 +1507,7 @@ namespace etl //************************************************************************* unordered_multiset& operator = (unordered_multiset&& rhs) { - // Skip if doing self assignment - if (this != &rhs) - { - base::clear(); - base::move(rhs.begin(), rhs.end()); - } + base::operator =(etl::move(rhs)); return *this; } diff --git a/include/etl/unordered_set.h b/include/etl/unordered_set.h index 0ffa77c8..a3b4203a 100644 --- a/include/etl/unordered_set.h +++ b/include/etl/unordered_set.h @@ -674,7 +674,7 @@ namespace etl while (inode != bucket.end()) { // Do we already have this key? - if (inode->key == key) + if (key_equal_function(inode->key, key)) { break; } @@ -747,7 +747,7 @@ namespace etl while (inode != bucket.end()) { // Do we already have this key? - if (inode->key == key) + if (key_equal_function(inode->key, key)) { break; } @@ -1161,6 +1161,8 @@ namespace etl // Skip if doing self assignment if (this != &rhs) { + key_hash_function = rhs.hash_function(); + key_equal_function = rhs.key_eq(); assign(rhs.cbegin(), rhs.cend()); } @@ -1177,6 +1179,8 @@ namespace etl if (this != &rhs) { clear(); + key_hash_function = rhs.hash_function(); + key_equal_function = rhs.key_eq(); move(rhs.begin(), rhs.end()); } @@ -1189,12 +1193,14 @@ namespace etl //********************************************************************* /// Constructor. //********************************************************************* - iunordered_set(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_) + iunordered_set(pool_t& node_pool_, bucket_t* pbuckets_, size_t number_of_buckets_, hasher key_hash_function_, key_equal key_equal_function_) : pnodepool(&node_pool_) , pbuckets(pbuckets_) , number_of_buckets(number_of_buckets_) , first(pbuckets) , last(pbuckets) + , key_hash_function(key_hash_function_) + , key_equal_function(key_equal_function_) { } @@ -1418,8 +1424,8 @@ namespace etl //************************************************************************* /// Default constructor. //************************************************************************* - unordered_set() - : base(node_pool, buckets, MAX_BUCKETS) + unordered_set(const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { } @@ -1427,7 +1433,7 @@ namespace etl /// Copy constructor. //************************************************************************* unordered_set(const unordered_set& other) - : base(node_pool, buckets, MAX_BUCKETS) + : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq()) { // Skip if doing self assignment if (this != &other) @@ -1441,7 +1447,7 @@ namespace etl /// Move constructor. //************************************************************************* unordered_set(unordered_set&& other) - : base(node_pool, buckets, MAX_BUCKETS) + : base(node_pool, buckets, MAX_BUCKETS, other.hash_function(), other.key_eq()) { // Skip if doing self assignment if (this != &other) @@ -1458,8 +1464,8 @@ namespace etl ///\param last The iterator to the last element + 1. //************************************************************************* template - unordered_set(TIterator first_, TIterator last_) - : base(node_pool, buckets, MAX_BUCKETS) + unordered_set(TIterator first_, TIterator last_, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { base::assign(first_, last_); } @@ -1468,8 +1474,8 @@ namespace etl //************************************************************************* /// Construct from initializer_list. //************************************************************************* - unordered_set(std::initializer_list init) - : base(node_pool, buckets, MAX_BUCKETS) + unordered_set(std::initializer_list init, const THash& hash = THash(), const TKeyEqual& equal = TKeyEqual()) + : base(node_pool, buckets, MAX_BUCKETS, hash, equal) { base::assign(init.begin(), init.end()); } @@ -1488,11 +1494,7 @@ namespace etl //************************************************************************* unordered_set& operator = (const unordered_set& rhs) { - // Skip if doing self assignment - if (this != &rhs) - { - base::assign(rhs.cbegin(), rhs.cend()); - } + base::operator=(rhs); return *this; } @@ -1503,12 +1505,7 @@ namespace etl //************************************************************************* unordered_set& operator = (unordered_set&& rhs) { - // Skip if doing self assignment - if (this != &rhs) - { - base::clear(); - base::move(rhs.begin(), rhs.end()); - } + base::operator=(etl::move(rhs)); return *this; } diff --git a/test/test_unordered_map.cpp b/test/test_unordered_map.cpp index 4f49203f..9efba58b 100644 --- a/test/test_unordered_map.cpp +++ b/test/test_unordered_map.cpp @@ -151,6 +151,48 @@ namespace etl namespace { + //*************************************************************************** + struct CustomHashFunction + { + CustomHashFunction() + : id(0) + { + } + + CustomHashFunction(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t e) const + { + return size_t(e); + } + + int id; + }; + + //*************************************************************************** + struct CustomKeyEq + { + CustomKeyEq() + : id(0) + { + } + + CustomKeyEq(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t lhs, uint32_t rhs) const + { + return (lhs == rhs); + } + + int id; + }; + SUITE(test_unordered_map) { static const size_t SIZE = 10; @@ -950,7 +992,9 @@ namespace CHECK_EQUAL('d', map[3]); } - TEST(test_ndc_hasher_and_key_eq) { + //************************************************************************* + TEST(test_ndc_hasher_and_key_eq) + { typedef etl::unordered_map Map; ndc_hash hasher1(1); ndc_hash hasher2(2); @@ -990,7 +1034,9 @@ namespace CHECK_EQUAL(7, moveAssigned[5]); } - TEST(test_parameterized_eq) { + //************************************************************************* + TEST(test_parameterized_eq) + { constexpr std::size_t MODULO = 4; parameterized_hash hash{MODULO}; parameterized_equal eq{MODULO}; @@ -1012,5 +1058,72 @@ namespace map.erase(2); CHECK(map.find(6) == map.end()); } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_copy_construct) + { + CustomHashFunction chf(1); + CustomKeyEq ceq(2); + + etl::unordered_map set1(chf, ceq); + etl::unordered_map set2(set1); + + CHECK_EQUAL(chf.id, set2.hash_function().id); + CHECK_EQUAL(ceq.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_assignment) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + CustomHashFunction chf3(3); + CustomKeyEq ceq4(4); + + etl::unordered_map set1(chf1, ceq2); + etl::unordered_map set2(chf3, ceq4); + + set2.operator=(set1); + + CHECK_EQUAL(chf1.id, set2.hash_function().id); + CHECK_EQUAL(ceq2.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_iterators) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + using value_type = etl::unordered_map::value_type; + std::array data = + { + value_type{1, 11}, + value_type{2, 22}, + value_type{3, 33}, + value_type{4, 44}, + value_type{5, 55} + }; + + etl::unordered_map set1(data.begin(), data.end(), chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_initializer_list) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + using value_type = etl::unordered_map::value_type; + + etl::unordered_map set1({ value_type{1, 11}, value_type{2, 22}, value_type{3, 33}, value_type{4, 44}, value_type{5, 55} }, chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } }; } diff --git a/test/test_unordered_multimap.cpp b/test/test_unordered_multimap.cpp index ab50ae13..863a14e2 100644 --- a/test/test_unordered_multimap.cpp +++ b/test/test_unordered_multimap.cpp @@ -90,6 +90,48 @@ namespace typedef ETL_OR_STD::pair ElementDC; typedef ETL_OR_STD::pair ElementNDC; + //*************************************************************************** + struct CustomHashFunction + { + CustomHashFunction() + : id(0) + { + } + + CustomHashFunction(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t e) const + { + return size_t(e); + } + + int id; + }; + + //*************************************************************************** + struct CustomKeyEq + { + CustomKeyEq() + : id(0) + { + } + + CustomKeyEq(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t lhs, uint32_t rhs) const + { + return (lhs == rhs); + } + + int id; + }; + SUITE(test_unordered_multimap) { static const size_t SIZE = 10; @@ -826,5 +868,72 @@ namespace CHECK_EQUAL("map[2] = c", s[0]); CHECK_EQUAL("map[3] = d", s[1]); } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_copy_construct) + { + CustomHashFunction chf(1); + CustomKeyEq ceq(2); + + etl::unordered_multimap set1(chf, ceq); + etl::unordered_multimap set2(set1); + + CHECK_EQUAL(chf.id, set2.hash_function().id); + CHECK_EQUAL(ceq.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_assignment) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + CustomHashFunction chf3(3); + CustomKeyEq ceq4(4); + + etl::unordered_multimap set1(chf1, ceq2); + etl::unordered_multimap set2(chf3, ceq4); + + set2.operator=(set1); + + CHECK_EQUAL(chf1.id, set2.hash_function().id); + CHECK_EQUAL(ceq2.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_iterators) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + using value_type = etl::unordered_multimap::value_type; + std::array data = + { + value_type{1, 11}, + value_type{2, 22}, + value_type{3, 33}, + value_type{4, 44}, + value_type{5, 55} + }; + + etl::unordered_multimap set1(data.begin(), data.end(), chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_initializer_list) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + using value_type = etl::unordered_multimap::value_type; + + etl::unordered_multimap set1({ value_type{1, 11}, value_type{2, 22}, value_type{3, 33}, value_type{4, 44}, value_type{5, 55} }, chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } }; } diff --git a/test/test_unordered_multiset.cpp b/test/test_unordered_multiset.cpp index 7ddc43a9..4e532cf6 100644 --- a/test/test_unordered_multiset.cpp +++ b/test/test_unordered_multiset.cpp @@ -63,6 +63,48 @@ namespace etl namespace { + //*************************************************************************** + struct CustomHashFunction + { + CustomHashFunction() + : id(0) + { + } + + CustomHashFunction(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t e) const + { + return size_t(e); + } + + int id; + }; + + //*************************************************************************** + struct CustomKeyEq + { + CustomKeyEq() + : id(0) + { + } + + CustomKeyEq(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t lhs, uint32_t rhs) const + { + return (lhs == rhs); + } + + int id; + }; + SUITE(test_unordered_multiset) { static const size_t SIZE = 10; @@ -727,5 +769,62 @@ namespace data.assign(initial_data.begin(), initial_data.end()); CHECK_CLOSE(2.0, data.load_factor(), 0.01); } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_copy_construct) + { + CustomHashFunction chf(1); + CustomKeyEq ceq(2); + + etl::unordered_multiset set1(chf, ceq); + etl::unordered_multiset set2(set1); + + CHECK_EQUAL(chf.id, set2.hash_function().id); + CHECK_EQUAL(ceq.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_assignment) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + CustomHashFunction chf3(3); + CustomKeyEq ceq4(4); + + etl::unordered_multiset set1(chf1, ceq2); + etl::unordered_multiset set2(chf3, ceq4); + + set2.operator=(set1); + + CHECK_EQUAL(chf1.id, set2.hash_function().id); + CHECK_EQUAL(ceq2.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_iterators) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + std::array data = { 1, 2, 3, 4, 5 }; + + etl::unordered_multiset set1(data.begin(), data.end(), chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_initializer_list) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + etl::unordered_multiset set1({ 1, 2, 3, 4, 5 }, chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } }; } diff --git a/test/test_unordered_set.cpp b/test/test_unordered_set.cpp index 17af20a5..5f542043 100644 --- a/test/test_unordered_set.cpp +++ b/test/test_unordered_set.cpp @@ -63,6 +63,49 @@ namespace etl namespace { + //*************************************************************************** + struct CustomHashFunction + { + CustomHashFunction() + : id(0) + { + } + + CustomHashFunction(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t e) const + { + return size_t(e); + } + + int id; + }; + + //*************************************************************************** + struct CustomKeyEq + { + CustomKeyEq() + : id(0) + { + } + + CustomKeyEq(int id_) + : id(id_) + { + } + + size_t operator ()(uint32_t lhs, uint32_t rhs) const + { + return (lhs == rhs); + } + + int id; + }; + + //*************************************************************************** SUITE(test_unordered_set) { static const size_t SIZE = 10; @@ -663,5 +706,62 @@ namespace CHECK_EQUAL("set = 2", s[0]); CHECK_EQUAL("set = 3", s[1]); } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_copy_construct) + { + CustomHashFunction chf(1); + CustomKeyEq ceq(2); + + etl::unordered_set set1(chf, ceq); + etl::unordered_set set2(set1); + + CHECK_EQUAL(chf.id, set2.hash_function().id); + CHECK_EQUAL(ceq.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_assignment) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + CustomHashFunction chf3(3); + CustomKeyEq ceq4(4); + + etl::unordered_set set1(chf1, ceq2); + etl::unordered_set set2(chf3, ceq4); + + set2.operator=(set1); + + CHECK_EQUAL(chf1.id, set2.hash_function().id); + CHECK_EQUAL(ceq2.id, set2.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_iterators) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + std::array data = { 1, 2, 3, 4, 5 }; + + etl::unordered_set set1(data.begin(), data.end(), chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } + + //************************************************************************* + TEST(test_copying_of_hash_and_key_compare_with_construction_from_initializer_list) + { + CustomHashFunction chf1(1); + CustomKeyEq ceq2(2); + + etl::unordered_set set1({ 1, 2, 3, 4, 5 }, chf1, ceq2); + + CHECK_EQUAL(chf1.id, set1.hash_function().id); + CHECK_EQUAL(ceq2.id, set1.key_eq().id); + } }; }