From 62ffe81c1f79bf246a20d01d126ed7474f1cf2ee Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 22 Jun 2025 11:13:07 +0100 Subject: [PATCH] Modified to have iconst_map base type --- include/etl/const_map.h | 129 +++++++++++++--- test/test_const_map.cpp | 316 ++++++++++++++++++++++++---------------- 2 files changed, 293 insertions(+), 152 deletions(-) diff --git a/include/etl/const_map.h b/include/etl/const_map.h index e31c9641..fd5f9606 100644 --- a/include/etl/const_map.h +++ b/include/etl/const_map.h @@ -44,8 +44,8 @@ SOFTWARE. namespace etl { - template > - class const_map + template + class iconst_map { public: @@ -106,23 +106,6 @@ namespace etl key_compare kcompare; }; - //************************************************************************* - ///\brief Construct a const_map from a variadic list of elements. - /// Static asserts if the element type is not constructible. - /// Static asserts if the elements are not of type value_type. - /// Static asserts if the number of elements is greater than the capacity of the const_map. - //************************************************************************* - template - ETL_CONSTEXPR14 explicit const_map(TElements&&... elements) ETL_NOEXCEPT - : element_list{etl::forward(elements)...} - , element_list_end{element_list + sizeof...(elements)} - { - static_assert((etl::is_default_constructible::value), "key_type must be default constructible"); - static_assert((etl::is_default_constructible::value), "mapped_type must be default constructible"); - static_assert((etl::are_all_same...>::value), "All elements must be value_type"); - static_assert(sizeof...(elements) <= Size, "Number of elements exceeds capacity"); - } - //************************************************************************* /// Check that the elements are valid for a map. /// The elements must be sorted and contain no duplicates. @@ -403,7 +386,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 size_type full() const ETL_NOEXCEPT { - return size() == Size; + return size() == max_elements; } //************************************************************************* @@ -421,7 +404,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 size_type max_size() const ETL_NOEXCEPT { - return Size; + return max_elements; } //************************************************************************* @@ -431,7 +414,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 size_type capacity() const ETL_NOEXCEPT { - return Size; + return max_elements; } //************************************************************************* @@ -452,6 +435,19 @@ namespace etl return vcompare; } + protected: + + //************************************************************************* + /// Constructor + //************************************************************************* + template + ETL_CONSTEXPR14 explicit iconst_map(value_type* element_list_, size_type size_, size_type max_elements_) ETL_NOEXCEPT + : element_list(element_list_) + , element_list_end{element_list_ + size_} + , max_elements(max_elements_) + { + } + private: //********************************************************************* @@ -474,8 +470,54 @@ namespace etl value_compare vcompare; - value_type element_list[Size]; + value_type* element_list; value_type* element_list_end; + size_type max_elements; + }; + + //********************************************************************* + /// + //********************************************************************* + template > + class const_map : public etl::iconst_map + { + public: + + using base_t = etl::iconst_map; + + using key_type = base_t::key_type; + using value_type = base_t::value_type; + using mapped_type = base_t::mapped_type ; + using key_compare = base_t::key_compare; + using const_reference = base_t::const_reference; + using const_pointer = base_t::const_pointer; + using const_iterator = base_t::const_iterator; + using size_type = base_t::size_type; + + /// Defines the parameter types + using const_key_reference = const key_type&; + using const_mapped_reference = const mapped_type&; + + //************************************************************************* + ///\brief Construct a const_map from a variadic list of elements. + /// Static asserts if the element type is not constructible. + /// Static asserts if the elements are not of type value_type. + /// Static asserts if the number of elements is greater than the capacity of the const_map. + //************************************************************************* + template + ETL_CONSTEXPR14 explicit const_map(TElements&&... elements) ETL_NOEXCEPT + : iconst_map(element_list, sizeof...(elements), Size) + , element_list{etl::forward(elements)...} + { + static_assert((etl::is_default_constructible::value), "key_type must be default constructible"); + static_assert((etl::is_default_constructible::value), "mapped_type must be default constructible"); + static_assert((etl::are_all_same...>::value), "All elements must be value_type"); + static_assert(sizeof...(elements) <= Size, "Number of elements exceeds capacity"); + } + + private: + + value_type element_list[Size]; }; //************************************************************************* @@ -488,7 +530,6 @@ namespace etl sizeof...(TPairs)>; #endif - //************************************************************************* /// Equality test. //************************************************************************* @@ -508,6 +549,46 @@ namespace etl { return !(lhs == rhs); } + + //************************************************************************* + /// Less-than. + //************************************************************************* + template + ETL_CONSTEXPR14 bool operator <(const etl::const_map& lhs, + const etl::const_map& rhs) + { + return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), TKeyCompare()); + } + + //************************************************************************* + /// Greater-than. + //************************************************************************* + template + ETL_CONSTEXPR14 bool operator >(const etl::const_map& lhs, + const etl::const_map& rhs) + { + return (rhs < lhs); + } + + //************************************************************************* + /// Less-than-equal. + //************************************************************************* + template + ETL_CONSTEXPR14 bool operator <=(const etl::const_map& lhs, + const etl::const_map& rhs) + { + return !(rhs < lhs); + } + + //************************************************************************* + /// Greater-than-equal. + //************************************************************************* + template + ETL_CONSTEXPR14 bool operator >=(const etl::const_map& lhs, + const etl::const_map& rhs) + { + return !(lhs < rhs); + } } #endif diff --git a/test/test_const_map.cpp b/test/test_const_map.cpp index 082efe99..bf46b579 100644 --- a/test/test_const_map.cpp +++ b/test/test_const_map.cpp @@ -111,6 +111,7 @@ namespace #define TEST_GREATER_THAN #ifdef TEST_GREATER_THAN using Data = etl::const_map>; + using IData = etl::iconst_map>; using DataTransparentComparator = etl::const_map>; #else using Data = etl::const_map>; @@ -197,6 +198,37 @@ namespace CHECK_FALSE(begin == end); } + //************************************************************************* + TEST(test_constructor_max_size_status_from_iconst_map) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + static constexpr const IData& idata = data; + + static constexpr bool is_valid = idata.is_valid(); + static constexpr size_t size = idata.size(); + static constexpr bool empty = idata.empty(); + static constexpr bool full = idata.full(); + static constexpr size_t capacity = idata.capacity(); + static constexpr size_t max_size = idata.max_size(); + static constexpr Data::const_iterator begin = idata.begin(); + static constexpr Data::const_iterator end = idata.end(); + + CHECK_TRUE(is_valid); + CHECK_TRUE(size == Max_Size); + CHECK_FALSE(empty); + CHECK_TRUE(full); + CHECK_TRUE(capacity == Max_Size); + CHECK_TRUE(max_size == Max_Size); + CHECK_FALSE(begin == end); + } + ////************************************************************************* // Enable to check static_assert "Number of elements exceeds capacity" ////************************************************************************* @@ -1592,138 +1624,62 @@ namespace CHECK_TRUE(data1 != data3); } -// //************************************************************************* -// TEST(test_key_compare) -// { -// const Data data(initial_data.begin(), initial_data.end()); -// -// Data::key_compare compare = data.key_comp(); -// -// Data::key_type a(Key('A'); -// Data::key_type b(Key('B'); -// -//#ifdef TEST_GREATER_THAN -// CHECK(!compare(a, b)); -// CHECK(compare(b, a)); -//#else -// CHECK(compare(a, b)); -// CHECK(!compare(b, a)); -//#endif -// } + //************************************************************************* + TEST(test_key_compare) + { + static constexpr Data data; -// //************************************************************************* -// TEST(test_key_compare_using_transparent_comparator) -// { -// using EMap = etl::map>; -// const EMap data(initial_data.begin(), initial_data.end()); -// -// EMap::key_compare compare = data.key_comp(); -// -// char a(Key('A'); -// Key b(Key('B'); -// -// CHECK(compare(a, b)); -// CHECK(!compare(b, a)); -// } + static constexpr Data::key_compare compare = data.key_comp(); -// //************************************************************************* -// TEST(test_value_compare) -// { -// const Data data(initial_data.begin(), initial_data.end()); -// -// Data::value_compare compare = data.value_comp(); -// -// Data::value_type a(char(Key('A'), 0); -// Data::value_type b(char(Key('B'), 1); -// -//#ifdef TEST_GREATER_THAN -// CHECK(!compare(a, b)); -// CHECK(compare(b, a)); -//#else -// CHECK(compare(a, b)); -// CHECK(!compare(b, a)); -//#endif -// } + static constexpr Data::key_type a(Key('A')); + static constexpr Data::key_type b(Key('B')); -// //************************************************************************* -// TEST(test_compare_lower_upper_bound) -// { -// Data data(initial_data_even.begin(), initial_data_even.end()); -// Compare_Data compare(initial_data_even.begin(), initial_data_even.end()); -// -// std::vector > tab(test_data.begin(), test_data.end()); -// -// //make sure both data and compare contain same elements -// std::vector > data_elements(data.begin(), data.end()); -// std::vector > compare_data_elements(compare.begin(), compare.end()); -// -// CHECK(data_elements == compare_data_elements); -// CHECK(data_elements.size() == Max_Size); -// -// for(std::vector >::iterator it = tab.begin() ; it != tab.end() ; ++it) -// { -// char i = it->first; -// -// //lower_bound -// CHECK((compare.lower_bound(i) == compare.end()) == (data.lower_bound(i) == data.end())); -// //if both end, or none -// if((compare.lower_bound(i) == compare.end()) == (data.lower_bound(i) == data.end())) -// { -// //if both are not end -// if(compare.lower_bound(i) != compare.end()) -// { -// CHECK((*compare.lower_bound(i)) == (*data.lower_bound(i))); -// } -// -// ETL_OR_STD::pair stlret = compare.equal_range(i); -// ETL_OR_STD::pair etlret = data.equal_range(i); -// -// CHECK((stlret.first == compare.end()) == (etlret.first == data.end())); -// if((stlret.first != compare.end()) && (etlret.first != data.end())) -// { -// CHECK((*stlret.first) == (*etlret.first)); -// } -// CHECK((stlret.second == compare.end()) == (etlret.second == data.end())); -// if((stlret.second != compare.end()) && (etlret.second != data.end())) -// { -// CHECK((*stlret.second) == (*etlret.second)); -// } -// } -// -// //upper_bound -// CHECK((compare.upper_bound(i) == compare.end()) == (data.upper_bound(i) == data.end())); -// //if both end, or none -// if((compare.upper_bound(i) == compare.end()) == (data.upper_bound(i) == data.end())) -// { -// //if both are not end -// if(compare.upper_bound(i) != compare.end()) -// { -// CHECK((*compare.upper_bound(i)) == (*data.upper_bound(i))); -// } -// } -// } -// } +#ifdef TEST_GREATER_THAN + CHECK(!compare(a, b)); + CHECK(compare(b, a)); +#else + CHECK(compare(a, b)); + CHECK(!compare(b, a)); +#endif + } -// //************************************************************************* -//#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) -// TEST(test_map_template_deduction) -// { -// using Pair = std::pair, int>; -// -// etl::map data { Pair{'0', 0}, Pair{'1', 1}, Pair{'2', 2}, Pair{'3', 3}, Pair{'4', 4}, Pair{'5', 5} }; -// -// auto v = *data.begin(); -// using Type = decltype(v); -// CHECK((std::is_same_v)); -// -// CHECK_EQUAL(0, data.at('0')); -// CHECK_EQUAL(1, data.at('1')); -// CHECK_EQUAL(2, data.at('2')); -// CHECK_EQUAL(3, data.at('3')); -// CHECK_EQUAL(4, data.at('4')); -// CHECK_EQUAL(5, data.at('5')); -// } -//#endif + //************************************************************************* + TEST(test_key_compare_using_transparent_comparator) + { + static constexpr DataTransparentComparator data; + + static constexpr DataTransparentComparator::key_compare compare = data.key_comp(); + + static constexpr DataTransparentComparator::key_type a(Key('A')); + static constexpr DataTransparentComparator::key_type b(Key('B')); + +#ifdef TEST_GREATER_THAN + CHECK(!compare(a, b)); + CHECK(compare(b, a)); +#else + CHECK(compare(a, b)); + CHECK(!compare(b, a)); +#endif + } + + //************************************************************************* + TEST(test_value_compare) + { + static constexpr Data data; + + static constexpr Data::value_compare compare = data.value_comp(); + + static constexpr Data::value_type a(Key('A'), 0); + static constexpr Data::value_type b(Key('B'), 1); + +#ifdef TEST_GREATER_THAN + CHECK(!compare(a, b)); + CHECK(compare(b, a)); +#else + CHECK(compare(a, b)); + CHECK(!compare(b, a)); +#endif + } //************************************************************************* TEST(test_contains) @@ -2074,6 +2030,110 @@ namespace CHECK_TRUE(compareAB1); CHECK_TRUE(compareAB2); CHECK_TRUE(compareAB3); +#endif + } + + //************************************************************************* + TEST(test_less_than) + { + static constexpr DataTransparentComparator data1{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('B'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data2{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data3{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('D'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + +#ifdef TEST_GREATER_THAN + CHECK_FALSE(data1 < data2); + CHECK_FALSE(data2 < data3); + CHECK_TRUE(data2 < data1); + CHECK_TRUE(data3 < data2); +#else + CHECK_TRUE(data1 < data2); + CHECK_TRUE(data2 < data3); + CHECK_FALSE(data2 < data1); + CHECK_FALSE(data3 < data2); +#endif + } + + //************************************************************************* + TEST(test_less_than_equal) + { + static constexpr DataTransparentComparator data1{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('B'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data2{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data3{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('D'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + +#ifdef TEST_GREATER_THAN + CHECK_FALSE(data1 <= data2); + CHECK_FALSE(data2 <= data3); + CHECK_TRUE(data2 <= data1); + CHECK_TRUE(data3 <= data2); + CHECK_TRUE(data1 <= data1); +#else + CHECK_TRUE(data1 <= data2); + CHECK_TRUE(data2 <= data3); + CHECK_FALSE(data2 <= data1); + CHECK_FALSE(data3 <= data2); + CHECK_TRUE(data1 <= data1); +#endif + } + + //************************************************************************* + TEST(test_greater_than) + { + static constexpr DataTransparentComparator data1{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('B'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data2{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data3{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('D'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + +#ifdef TEST_GREATER_THAN + CHECK_TRUE(data1 > data2); + CHECK_TRUE(data2 > data3); + CHECK_FALSE(data2 > data1); + CHECK_FALSE(data3 > data2); +#else + CHECK_FALSE(data1 > data2); + CHECK_FALSE(data2 > data3); + CHECK_TRUE(data2 > data1); + CHECK_TRUE(data3 > data2); +#endif + } + + //************************************************************************* + TEST(test_greater_than_equal) + { + static constexpr DataTransparentComparator data1{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('B'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data2{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + + static constexpr DataTransparentComparator data3{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('D'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + +#ifdef TEST_GREATER_THAN + CHECK_TRUE(data1 >= data2); + CHECK_TRUE(data2 >= data3); + CHECK_FALSE(data2 >= data1); + CHECK_FALSE(data3 >= data2); + CHECK_TRUE(data1 <= data1); +#else + CHECK_FALSE(data1 >= data2); + CHECK_FALSE(data2 >= data3); + CHECK_TRUE(data2 >= data1); + CHECK_TRUE(data3 >= data2); + CHECK_TRUE(data1 <= data1); #endif } };