From 8f860964d4f192f83a55dde0a240919c20b3c713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20M=C3=BCller?= Date: Sun, 9 Feb 2020 11:50:50 +0100 Subject: [PATCH 1/5] Default to automatic profile detection if no profile is set (#192) --- include/etl/profiles/etl_profile.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/profiles/etl_profile.h b/include/etl/profiles/etl_profile.h index 9ef6b03a..bce6871d 100644 --- a/include/etl/profiles/etl_profile.h +++ b/include/etl/profiles/etl_profile.h @@ -58,7 +58,7 @@ SOFTWARE. #elif defined(PROFILE_CUSTOM) #include "custom_profile.h" #else - #error Must provide a profile header file when buiding ETL. See https://www.etlcpp.com/setup.html + #include "auto.h" #endif #endif // __ETL_PROFILE_H_ From 9dd88e188522d27111fcd1fe2f3fc250547b7d67 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 11 Feb 2020 13:27:43 +0100 Subject: [PATCH 2/5] Merge remote-tracking branch 'origin/development' --- include/etl/algorithm.h | 116 ++++++-- include/etl/array.h | 18 +- include/etl/deque.h | 52 ++-- include/etl/file_error_numbers.txt | 1 + include/etl/flat_map.h | 110 +++++++- include/etl/flat_multimap.h | 109 +++++++- include/etl/flat_multiset.h | 133 +++++++-- include/etl/flat_set.h | 137 ++++++++-- include/etl/icache.h | 25 +- include/etl/map.h | 182 ++++++++++++- include/etl/memory.h | 254 ++++++++++++++++- include/etl/multimap.h | 151 ++++++++++- include/etl/multiset.h | 235 +++++++++++++--- include/etl/optional.h | 78 +++++- include/etl/packet.h | 41 +++ include/etl/platform.h | 37 ++- include/etl/queue.h | 85 +++++- include/etl/queue_mpmc_mutex.h | 94 ++++++- include/etl/queue_spsc_atomic.h | 64 ++++- include/etl/queue_spsc_isr.h | 137 ++++++++-- include/etl/queue_spsc_locked.h | 155 +++++++++-- include/etl/set.h | 255 +++++++++++++++--- include/etl/stack.h | 81 +++++- include/etl/type_traits.h | 31 ++- include/etl/type_traits_generator.h | 3 + include/etl/utility.h | 144 +++++++--- include/etl/vector.h | 36 +-- include/etl/version.h | 5 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 5 +- test/data.h | 2 + test/test_array.cpp | 6 - test/test_deque.cpp | 45 +++- test/test_flat_map.cpp | 38 +++ test/test_flat_multimap.cpp | 42 +++ test/test_flat_multiset.cpp | 44 +++ test/test_flat_set.cpp | 40 +++ test/test_list.cpp | 6 +- test/test_map.cpp | 119 +++++++- test/test_memory.cpp | 137 +++++++++- test/test_multimap.cpp | 95 ++++++- test/test_multiset.cpp | 98 ++++++- test/test_optional.cpp | 19 ++ test/test_packet.cpp | 40 ++- test/test_queue.cpp | 36 +++ test/test_queue_mpmc_mutex.cpp | 39 +++ test/test_queue_mpmc_mutex_small.cpp | 39 +++ test/test_queue_spsc_atomic.cpp | 39 +++ test/test_queue_spsc_atomic_small.cpp | 39 +++ test/test_queue_spsc_isr.cpp | 39 +++ test/test_queue_spsc_isr_small.cpp | 39 +++ test/test_queue_spsc_locked.cpp | 39 +++ test/test_queue_spsc_locked_small.cpp | 39 +++ test/test_set.cpp | 96 ++++++- test/test_type_traits.cpp | 26 +- test/test_utility.cpp | 39 +++ test/vs2017/.vs/etl/v15/.gitignore | 1 + test/vs2017/Debug No Unit Tests/.gitignore | 2 + .../Debug No Unit Tests/etl.tlog/.gitignore | 2 + test/vs2017/DebugNoSTL/.gitignore | 1 + 61 files changed, 3629 insertions(+), 395 deletions(-) create mode 100644 test/vs2017/.vs/etl/v15/.gitignore create mode 100644 test/vs2017/Debug No Unit Tests/.gitignore create mode 100644 test/vs2017/Debug No Unit Tests/etl.tlog/.gitignore create mode 100644 test/vs2017/DebugNoSTL/.gitignore diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 1cd8e4f7..31b0b0fc 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -318,6 +318,19 @@ namespace etl return db; } + + //*************************************************************************** + // move_s + template + TIterator2 move_s(TIterator1 sb, TIterator1 se, TIterator2 db, TIterator2 de) + { + while ((sb != se) && (db != de)) + { + *db++ = etl::move(*sb++); + } + + return db; + } #else //*************************************************************************** // move @@ -326,7 +339,39 @@ namespace etl { return std::move(sb, se, db); } + + //*************************************************************************** + // move_s + template + TIterator2 move_s(TIterator1 sb, TIterator1 se, TIterator2 db, TIterator2 de) + { + while ((sb != se) && (db != de)) + { + *db++ = etl::move(*sb++); + } + + return db; + } #endif +#else + // C++03 + //*************************************************************************** + // move + template + TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + // Move not supported. Defer to copy. + return etl::copy(sb, se, db); + } + + //*************************************************************************** + // move_s + template + TIterator2 move_s(TIterator1 sb, TIterator1 se, TIterator2 db, TIterator2 de) + { + // Move not supported. Defer to copy. + return etl::copy_s(sb, se, db, de); + } #endif #if ETL_CPP11_SUPPORTED @@ -352,6 +397,15 @@ namespace etl return std::move_backward(sb, se, de); } #endif +#else + //*************************************************************************** + // move_backward + template + TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + // Move not supported. Defer to copy_backward. + return std::copy_backward(sb, se, de); + } #endif #if defined(ETL_NO_STL) @@ -975,7 +1029,7 @@ namespace etl { if (compare(first[child2nd], first[child2nd - 1])) { - child2nd--; + --child2nd; } first[value_index] = first[child2nd]; @@ -1022,8 +1076,8 @@ namespace etl typedef typename etl::iterator_traits::value_type value_t; typedef typename etl::iterator_traits::difference_type distance_t; - value_t value = last[-1]; - last[-1] = first[0]; + value_t value = etl::move(last[-1]); + last[-1] = etl::move(first[0]); private_heap::adjust_heap(first, distance_t(0), distance_t(last - first - 1), value, compare); } @@ -1095,7 +1149,7 @@ namespace etl // Is Heap template ETL_NODISCARD - bool is_heap(TIterator first, TIterator last) + bool is_heap(TIterator first, TIterator last) { typedef etl::less::value_type> compare; @@ -1109,6 +1163,27 @@ namespace etl { return private_heap::is_heap(first, last - first, compare); } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last) + { + while (first != last) + { + etl::pop_heap(first, last--); + } + } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last, TCompare compare) + { + while (first != last) + { + etl::pop_heap(first, last--, compare); + } + } + #else //*************************************************************************** // Heap @@ -1154,6 +1229,14 @@ namespace etl std::make_heap(first, last); } + // Is Heap + template + ETL_NODISCARD + bool is_heap(TIterator first, TIterator last, TCompare compare) + { + return std::is_heap(first, last, compare); + } + // Is Heap template ETL_NODISCARD @@ -1162,13 +1245,20 @@ namespace etl return std::is_heap(first, last); } - // Is Heap + // Sort Heap template - ETL_NODISCARD - bool is_heap(TIterator first, TIterator last, TCompare compare) + void sort_heap(TIterator first, TIterator last, TCompare compare) { - return std::is_heap(first, last, compare); + std::sort_heap(first, last, compare); } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last) + { + std::sort_heap(first, last); + } + #endif #if defined (ETL_NO_STL) @@ -2951,10 +3041,7 @@ namespace etl etl::make_heap(first, last, compare); } - while (first != last) - { - etl::pop_heap(first, last--, compare); - } + etl::sort_heap(first, last, compare); } //*************************************************************************** @@ -2969,10 +3056,7 @@ namespace etl etl::make_heap(first, last); } - while (first != last) - { - etl::pop_heap(first, last--); - } + etl::sort_heap(first, last); } //*************************************************************************** diff --git a/include/etl/array.h b/include/etl/array.h index e0167dd7..760b0762 100644 --- a/include/etl/array.h +++ b/include/etl/array.h @@ -361,7 +361,6 @@ namespace etl //************************************************************************* /// Fills the array from the range. - /// If the range is larger than the array then the extra data is ignored. /// If the range is smaller than the array then the unused array elements are left unmodified. ///\param first The iterator to the first item in the ramge. ///\param last The iterator to one past the final item in the range. @@ -374,7 +373,6 @@ namespace etl //************************************************************************* /// Fills the array from the range. - /// If the range is larger than the array then the extra data is ignored. /// If the range is smaller than the array then the unused array elements are initialised with the supplied value. ///\param first The iterator to the first item in the ramge. ///\param last The iterator to one past the final item in the range. @@ -383,9 +381,9 @@ namespace etl void assign(TIterator first, const TIterator last, parameter_t value) { // Copy from the range. - iterator p = etl::copy_s(first, last, begin(), end()); + iterator p = etl::copy(first, last, begin()); - // Default initialise any that are left. + // Initialise any that are left. etl::fill(p, end(), value); } @@ -408,7 +406,7 @@ namespace etl { iterator p = const_cast(position); - etl::copy_backward(p, end() - 1, end()); + etl::move_backward(p, end() - 1, end()); *p = value; return p; @@ -445,7 +443,7 @@ namespace etl if (source_size < destination_space) { size_t length = SIZE - (etl::distance(begin(), p) + source_size); - etl::copy_backward(p, p + length, end()); + etl::move_backward(p, p + length, end()); } // Copy from the range. @@ -472,7 +470,7 @@ namespace etl iterator erase(const_iterator position) { iterator p = const_cast(position); - etl::copy(p + 1, end(), p); + etl::move(p + 1, end(), p); return p; } @@ -497,7 +495,7 @@ namespace etl iterator erase(const_iterator first, const_iterator last) { iterator p = const_cast(first); - etl::copy(last, cend(), p); + etl::move(last, cend(), p); return p; } @@ -520,7 +518,7 @@ namespace etl { iterator p = const_cast(position); - etl::copy(p + 1, end(), p); + etl::move(p + 1, end(), p); back() = value; return p; @@ -546,7 +544,7 @@ namespace etl { iterator p = const_cast(first); - p = etl::copy(last, cend(), p); + p = etl::move(last, cend(), p); etl::fill(p, end(), value); return const_cast(first); diff --git a/include/etl/deque.h b/include/etl/deque.h index 522953e0..9f35008f 100644 --- a/include/etl/deque.h +++ b/include/etl/deque.h @@ -901,7 +901,7 @@ namespace etl create_element_front(*_begin); // Move the values. - etl::copy(_begin + 1, position, _begin); + etl::move(_begin + 1, position, _begin); // Write the new value. *--position = value; @@ -912,7 +912,7 @@ namespace etl create_element_back(*(_end - 1)); // Move the values. - etl::copy_backward(position, _end - 2, _end - 1); + etl::move_backward(position, _end - 2, _end - 1); // Write the new value. *position = value; @@ -1016,7 +1016,7 @@ namespace etl create_element_front(*_begin); // Move the values. - etl::copy(_begin + 1, position, _begin); + etl::move(_begin + 1, position, _begin); // Write the new value. --position; @@ -1029,7 +1029,7 @@ namespace etl create_element_back(*(_end - 1)); // Move the values. - etl::copy_backward(position, _end - 2, _end - 1); + etl::move_backward(position, _end - 2, _end - 1); // Write the new value. (*position).~T(); @@ -1083,7 +1083,7 @@ namespace etl create_element_front(*_begin); // Move the values. - etl::copy(_begin + 1, position, _begin); + etl::move(_begin + 1, position, _begin); // Write the new value. --position; @@ -1096,7 +1096,7 @@ namespace etl create_element_back(*(_end - 1)); // Move the values. - etl::copy_backward(position, _end - 2, _end - 1); + etl::move_backward(position, _end - 2, _end - 1); // Write the new value. (*position).~T(); @@ -1148,7 +1148,7 @@ namespace etl create_element_front(*_begin); // Move the values. - etl::copy(_begin + 1, position, _begin); + etl::move(_begin + 1, position, _begin); // Write the new value. --position; @@ -1161,7 +1161,7 @@ namespace etl create_element_back(*(_end - 1)); // Move the values. - etl::copy_backward(position, _end - 2, _end - 1); + etl::move_backward(position, _end - 2, _end - 1); // Write the new value. (*position).~T(); @@ -1213,7 +1213,7 @@ namespace etl create_element_front(*_begin); // Move the values. - etl::copy(_begin + 1, position, _begin); + etl::move(_begin + 1, position, _begin); // Write the new value. --position; @@ -1226,7 +1226,7 @@ namespace etl create_element_back(*(_end - 1)); // Move the values. - etl::copy_backward(position, _end - 2, _end - 1); + etl::move_backward(position, _end - 2, _end - 1); // Write the new value. (*position).~T(); @@ -1278,7 +1278,7 @@ namespace etl create_element_front(*_begin); // Move the values. - etl::copy(_begin + 1, position, _begin); + etl::move(_begin + 1, position, _begin); // Write the new value. --position; @@ -1291,7 +1291,7 @@ namespace etl create_element_back(*(_end - 1)); // Move the values. - etl::copy_backward(position, _end - 2, _end - 1); + etl::move_backward(position, _end - 2, _end - 1); // Write the new value. (*position).~T(); @@ -1367,10 +1367,10 @@ namespace etl create_element_front(*from--); } - // Copy old. + // Move old. from = position - n_copy_old; to = _begin + n_create_copy; - etl::copy_n(from, n_copy_old, to); + etl::move(from, from + n_copy_old, to); // Copy new. to = position - n_create_copy; @@ -1401,8 +1401,8 @@ namespace etl create_element_back(*from++); } - // Copy old. - etl::copy_backward(position, position + n_copy_old, position + n_insert + n_copy_old); + // Move old. + etl::move_backward(position, position + n_copy_old, position + n_insert + n_copy_old); // Copy new. etl::fill_n(position, n_copy_new, value); @@ -1469,15 +1469,15 @@ namespace etl // Create copy. create_element_front(n_create_copy, _begin + n_create_new); - // Copy old. + // Move old. from = position - n_copy_old; to = _begin + n_create_copy; - etl::copy_n(from, n_copy_old, to); + etl::move(from, from + n_copy_old, to); // Copy new. to = position - n_create_copy; range_begin += n_create_new; - etl::copy_n(range_begin, n_copy_new, to); + etl::copy(range_begin, range_begin + n_copy_new, to); position = _begin + n_move; } @@ -1505,12 +1505,12 @@ namespace etl create_element_back(*from++); } - // Copy old. - etl::copy_backward(position, position + n_copy_old, position + n_insert + n_copy_old); + // Move old. + etl::move_backward(position, position + n_copy_old, position + n_insert + n_copy_old); // Copy new. item = range_begin; - etl::copy_n(item, n_copy_new, position); + etl::copy(item, item + n_copy_new, position); } } @@ -1543,13 +1543,13 @@ namespace etl // Are we closer to the front? if (distance(_begin, position) < difference_type(current_size / 2)) { - etl::copy_backward(_begin, position, position + 1); + etl::move_backward(_begin, position, position + 1); destroy_element_front(); ++position; } else { - etl::copy(position + 1, _end, position); + etl::move(position + 1, _end, position); destroy_element_back(); } } @@ -1599,7 +1599,7 @@ namespace etl if (distance(_begin, position) < difference_type(current_size / 2)) { // Move the items. - etl::copy_backward(_begin, position, position + length); + etl::move_backward(_begin, position, position + length); for (size_t i = 0; i < length; ++i) { @@ -1612,7 +1612,7 @@ namespace etl // Must be closer to the back. { // Move the items. - etl::copy(position + length, _end, position); + etl::move(position + length, _end, position); for (size_t i = 0; i < length; ++i) { diff --git a/include/etl/file_error_numbers.txt b/include/etl/file_error_numbers.txt index 23f13178..3961913e 100644 --- a/include/etl/file_error_numbers.txt +++ b/include/etl/file_error_numbers.txt @@ -51,3 +51,4 @@ 51 delegate 52 bitset 53 indirect_vector +54 queue_spsc_locked diff --git a/include/etl/flat_map.h b/include/etl/flat_map.h index 66494873..aa2c7b2c 100644 --- a/include/etl/flat_map.h +++ b/include/etl/flat_map.h @@ -71,13 +71,15 @@ namespace etl public: - typedef ETL_OR_STD::pair value_type; typedef TKey key_type; typedef TMapped mapped_type; typedef TKeyCompare key_compare; typedef value_type& reference; typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif typedef value_type* pointer; typedef const value_type* const_pointer; typedef size_t size_type; @@ -91,7 +93,7 @@ namespace etl protected: - typedef typename etl::parameter_type::type key_parameter_t; + typedef const key_type& key_parameter_t; private: @@ -305,6 +307,33 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Moves a value to the flat_map. + /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. + ///\param value The value to insert. + //********************************************************************* + ETL_OR_STD::pair insert(rvalue_reference value) + { + iterator i_element = lower_bound(value.first); + + ETL_OR_STD::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end()) || compare(value.first, i_element->first)) + { + ETL_ASSERT(!refmap_t::full(), ETL_ERROR(flat_map_full)); + + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + result = refmap_t::insert_at(i_element, *pvalue); + } + + return result; + } +#endif + //********************************************************************* /// Inserts a value to the flat_map. /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. @@ -316,6 +345,19 @@ namespace etl return insert(value).first; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Moves a value to the flat_map. + /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. + ///\param position The position to insert at. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, rvalue_reference value) + { + return insert(etl::move(value)).first; + } +#endif + //********************************************************************* /// Inserts a range of values to the flat_map. /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map does not have enough free space. @@ -690,6 +732,18 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iflat_map& operator = (iflat_map&& rhs) + { + move_container(etl::move(rhs)); + + return *this; + } +#endif + //************************************************************************* /// Gets the current size of the flat_map. ///\return The current size of the flat_map. @@ -755,6 +809,29 @@ namespace etl { } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move a flat_map. + /// Assumes the rhs is initialised and empty. + //************************************************************************* + void move_container(iflat_map&& rhs) + { + if (&rhs != this) + { + this->clear(); + + etl::iflat_map::iterator first = rhs.begin(); + etl::iflat_map::iterator last = rhs.end(); + + // Add all of the elements. + while (first != last) + { + this->insert(etl::move(*first++)); + } + } + } +#endif + private: // Disable copy construction. @@ -841,6 +918,20 @@ namespace etl this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + flat_map(flat_map&& other) + : etl::iflat_map(lookup, storage) + { + if (&other != this) + { + this->move_container(etl::move(other)); + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -886,6 +977,21 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + flat_map& operator = (flat_map&& rhs) + { + if (&rhs != this) + { + this->move_container(etl::move(rhs)); + } + + return *this; + } +#endif + private: typedef typename etl::iflat_map::value_type node_t; diff --git a/include/etl/flat_multimap.h b/include/etl/flat_multimap.h index d4066458..e25588fd 100644 --- a/include/etl/flat_multimap.h +++ b/include/etl/flat_multimap.h @@ -79,6 +79,9 @@ namespace etl typedef TKeyCompare key_compare; typedef value_type& reference; typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif typedef value_type* pointer; typedef const value_type* const_pointer; typedef size_t size_type; @@ -92,7 +95,7 @@ namespace etl protected: - typedef typename etl::parameter_type::type key_parameter_t; + typedef const key_type& key_parameter_t; private: @@ -270,9 +273,32 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED //********************************************************************* - /// Inserts a value to the flast_multi. - /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_map is already full. + /// Inserts a value to the flat_multimap. + /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap is already full. + ///\param value The value to insert. + //********************************************************************* + ETL_OR_STD::pair insert(rvalue_reference value) + { + ETL_ASSERT(!refmap_t::full(), ETL_ERROR(flat_multimap_full)); + + ETL_OR_STD::pair result(end(), false); + + iterator i_element = lower_bound(value.first); + + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + result = refmap_t::insert_at(i_element, *pvalue); + + return result; + } +#endif + + //********************************************************************* + /// Inserts a value to the flat_multimap. + /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap_full is already full. ///\param position The position to insert at. ///\param value The value to insert. //********************************************************************* @@ -281,6 +307,19 @@ namespace etl return insert(value).first; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Moves a value to the flat_multimap. + /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap_full is already full. + ///\param position The position to insert at. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, rvalue_reference value) + { + return insert(etl::move(value)).first; + } +#endif + //********************************************************************* /// Inserts a range of values to the flat_multimap. /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_multimap does not have enough free space. @@ -599,6 +638,18 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iflat_multimap& operator = (iflat_multimap&& rhs) + { + move_container(etl::move(rhs)); + + return *this; + } +#endif + //************************************************************************* /// Gets the current size of the flat_multiset. ///\return The current size of the flat_multiset. @@ -664,6 +715,29 @@ namespace etl { } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move a flat_multimap. + /// Assumes the rhs is initialised and empty. + //************************************************************************* + void move_container(iflat_multimap&& rhs) + { + if (&rhs != this) + { + this->clear(); + + etl::iflat_multimap::iterator first = rhs.begin(); + etl::iflat_multimap::iterator last = rhs.end(); + + // Add all of the elements. + while (first != last) + { + this->insert(etl::move(*first++)); + } + } + } +#endif + private: // Disable copy construction. @@ -748,6 +822,20 @@ namespace etl this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + flat_multimap(flat_multimap&& other) + : etl::iflat_multimap(lookup, storage) + { + if (&other != this) + { + this->move_container(etl::move(other)); + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -793,6 +881,21 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + flat_multimap& operator = (flat_multimap&& rhs) + { + if (&rhs != this) + { + this->move_container(etl::move(rhs)); + } + + return *this; + } +#endif + private: typedef typename etl::iflat_multimap::value_type node_t; diff --git a/include/etl/flat_multiset.h b/include/etl/flat_multiset.h index 23a793c7..9fbb870a 100644 --- a/include/etl/flat_multiset.h +++ b/include/etl/flat_multiset.h @@ -73,6 +73,9 @@ namespace etl typedef TKeyCompare key_compare; typedef value_type& reference; typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif typedef value_type* pointer; typedef const value_type* const_pointer; typedef size_t size_type; @@ -84,10 +87,6 @@ namespace etl typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; typedef typename etl::iterator_traits::difference_type difference_type; - protected: - - typedef typename etl::parameter_type::type parameter_t; - public: //********************************************************************* @@ -226,7 +225,7 @@ namespace etl /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset is already full. ///\param value The value to insert. //********************************************************************* - ETL_OR_STD::pair insert(parameter_t value) + ETL_OR_STD::pair insert(const_reference value) { ETL_OR_STD::pair result(end(), false); @@ -242,17 +241,53 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the flat_multiset. + /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset is already full. + ///\param value The value to insert. + //********************************************************************* + ETL_OR_STD::pair insert(rvalue_reference value) + { + ETL_OR_STD::pair result(end(), false); + + ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); + + iterator i_element = etl::lower_bound(begin(), end(), value, compare); + + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + result = refset_t::insert_at(i_element, *pvalue); + + return result; + } +#endif + //********************************************************************* /// Inserts a value to the flat_multiset. /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset is already full. ///\param position The position to insert at. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator position, parameter_t value) + iterator insert(iterator position, const_reference value) { return insert(value).first; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the flat_multiset. + /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset is already full. + ///\param position The position to insert at. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, rvalue_reference value) + { + return insert(etl::move(value)).first; + } +#endif + //********************************************************************* /// Inserts a range of values to the flat_multiset. /// If asserts or exceptions are enabled, emits flat_multiset_full if the flat_multiset does not have enough free space. @@ -273,7 +308,7 @@ namespace etl /// Emplaces a value to the set. //************************************************************************* template - ETL_OR_STD::pair emplace(parameter_t value) + ETL_OR_STD::pair emplace(const_reference value) { return insert(value); } @@ -375,7 +410,7 @@ namespace etl ///\param key The key to erase. ///\return The number of elements erased. 0 or 1. //********************************************************************* - size_t erase(parameter_t key) + size_t erase(const_reference key) { ETL_OR_STD::pair range = equal_range(key); @@ -455,7 +490,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pointing to the element or end() if not found. //********************************************************************* - iterator find(parameter_t key) + iterator find(const_reference key) { return refset_t::find(key); } @@ -465,7 +500,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pointing to the element or end() if not found. //********************************************************************* - const_iterator find(parameter_t key) const + const_iterator find(const_reference key) const { return refset_t::find(key); } @@ -475,7 +510,7 @@ namespace etl ///\param key The key to search for. ///\return 1 if the key exists, otherwise 0. //********************************************************************* - size_t count(parameter_t key) const + size_t count(const_reference key) const { return refset_t::count(key); } @@ -485,7 +520,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - iterator lower_bound(parameter_t key) + iterator lower_bound(const_reference key) { return refset_t::lower_bound(key); } @@ -495,7 +530,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - const_iterator lower_bound(parameter_t key) const + const_iterator lower_bound(const_reference key) const { return refset_t::lower_bound(key); } @@ -505,7 +540,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - iterator upper_bound(parameter_t key) + iterator upper_bound(const_reference key) { return refset_t::upper_bound(key); } @@ -515,7 +550,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - const_iterator upper_bound(parameter_t key) const + const_iterator upper_bound(const_reference key) const { return refset_t::upper_bound(key); } @@ -525,7 +560,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pair. //********************************************************************* - ETL_OR_STD::pair equal_range(parameter_t key) + ETL_OR_STD::pair equal_range(const_reference key) { return refset_t::equal_range(key); } @@ -535,7 +570,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pair. //********************************************************************* - ETL_OR_STD::pair equal_range(parameter_t key) const + ETL_OR_STD::pair equal_range(const_reference key) const { return refset_t::equal_range(key); } @@ -553,6 +588,18 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iflat_multiset& operator = (iflat_multiset&& rhs) + { + move_container(etl::move(rhs)); + + return *this; + } +#endif + //************************************************************************* /// Gets the current size of the flat_multiset. ///\return The current size of the flat_multiset. @@ -618,6 +665,29 @@ namespace etl { } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move a flat_multimap. + /// Assumes the rhs is initialised and empty. + //************************************************************************* + void move_container(iflat_multiset&& rhs) + { + if (&rhs != this) + { + this->clear(); + + etl::iflat_multiset::iterator first = rhs.begin(); + etl::iflat_multiset::iterator last = rhs.end(); + + // Add all of the elements. + while (first != last) + { + this->insert(etl::move(*first++)); + } + } + } +#endif + private: // Disable copy construction. @@ -703,6 +773,20 @@ namespace etl this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + flat_multiset(flat_multiset&& other) + : etl::iflat_multiset(lookup, storage) + { + if (&other != this) + { + this->move_container(etl::move(other)); + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -748,6 +832,21 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + flat_multiset& operator = (flat_multiset&& rhs) + { + if (&rhs != this) + { + this->move_container(etl::move(rhs)); + } + + return *this; + } +#endif + private: typedef typename etl::iflat_multiset::value_type node_t; diff --git a/include/etl/flat_set.h b/include/etl/flat_set.h index ff2aac95..1bdfb791 100644 --- a/include/etl/flat_set.h +++ b/include/etl/flat_set.h @@ -75,6 +75,9 @@ namespace etl typedef TKeyCompare key_compare; typedef value_type& reference; typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif typedef value_type* pointer; typedef const value_type* const_pointer; typedef size_t size_type; @@ -86,10 +89,6 @@ namespace etl typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; typedef typename etl::iterator_traits::difference_type difference_type; - protected: - - typedef typename etl::parameter_type::type parameter_t; - public: //********************************************************************* @@ -228,7 +227,7 @@ namespace etl /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set is already full. ///\param value The value to insert. //********************************************************************* - ETL_OR_STD::pair insert(parameter_t value) + ETL_OR_STD::pair insert(const_reference value) { iterator i_element = lower_bound(value); @@ -248,17 +247,57 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the flat_set. + /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set is already full. + ///\param value The value to insert. + //********************************************************************* + ETL_OR_STD::pair insert(rvalue_reference value) + { + iterator i_element = lower_bound(value); + + ETL_OR_STD::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end()) || compare(value, *i_element)) + { + ETL_ASSERT(!refset_t::full(), ETL_ERROR(flat_set_full)); + + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + result = refset_t::insert_at(i_element, *pvalue); + } + + return result; + } +#endif + //********************************************************************* /// Inserts a value to the flat_set. /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set is already full. ///\param position The position to insert at. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator position, parameter_t value) + iterator insert(iterator position, const_reference value) { return insert(value).first; } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the flat_set. + /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set is already full. + ///\param position The position to insert at. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator position, rvalue_reference value) + { + return insert(etl::move(value)).first; + } +#endif + //********************************************************************* /// Inserts a range of values to the flat_set. /// If asserts or exceptions are enabled, emits flat_set_full if the flat_set does not have enough free space. @@ -278,7 +317,7 @@ namespace etl //************************************************************************* /// Emplaces a value to the set. //************************************************************************* - ETL_OR_STD::pair emplace(parameter_t value) + ETL_OR_STD::pair emplace(const_reference value) { return insert(value); } @@ -455,7 +494,7 @@ namespace etl ///\param key The key to erase. ///\return The number of elements erased. 0 or 1. //********************************************************************* - size_t erase(parameter_t key) + size_t erase(const_reference key) { iterator i_element = find(key); @@ -538,7 +577,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pointing to the element or end() if not found. //********************************************************************* - iterator find(parameter_t key) + iterator find(const_reference key) { return refset_t::find(key); } @@ -548,7 +587,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pointing to the element or end() if not found. //********************************************************************* - const_iterator find(parameter_t key) const + const_iterator find(const_reference key) const { return refset_t::find(key); } @@ -558,7 +597,7 @@ namespace etl ///\param key The key to search for. ///\return 1 if the key exists, otherwise 0. //********************************************************************* - size_t count(parameter_t key) const + size_t count(const_reference key) const { return refset_t::count(key); } @@ -568,7 +607,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - iterator lower_bound(parameter_t key) + iterator lower_bound(const_reference key) { return refset_t::lower_bound(key); } @@ -578,7 +617,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - const_iterator lower_bound(parameter_t key) const + const_iterator lower_bound(const_reference key) const { return refset_t::lower_bound(key); } @@ -588,7 +627,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - iterator upper_bound(parameter_t key) + iterator upper_bound(const_reference key) { return refset_t::upper_bound(key); } @@ -598,7 +637,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator. //********************************************************************* - const_iterator upper_bound(parameter_t key) const + const_iterator upper_bound(const_reference key) const { return refset_t::upper_bound(key); } @@ -608,7 +647,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pair. //********************************************************************* - ETL_OR_STD::pair equal_range(parameter_t key) + ETL_OR_STD::pair equal_range(const_reference key) { return refset_t::equal_range(key); } @@ -618,7 +657,7 @@ namespace etl ///\param key The key to search for. ///\return An iterator pair. //********************************************************************* - ETL_OR_STD::pair equal_range(parameter_t key) const + ETL_OR_STD::pair equal_range(const_reference key) const { return refset_t::upper_bound(key); } @@ -636,6 +675,18 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iflat_set& operator = (iflat_set&& rhs) + { + move_container(etl::move(rhs)); + + return *this; + } +#endif + //************************************************************************* /// Gets the current size of the flat_set. ///\return The current size of the flat_set. @@ -701,6 +752,29 @@ namespace etl { } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move a flat_set. + /// Assumes the rhs is initialised and empty. + //************************************************************************* + void move_container(iflat_set&& rhs) + { + if (&rhs != this) + { + this->clear(); + + etl::iflat_set::iterator first = rhs.begin(); + etl::iflat_set::iterator last = rhs.end(); + + // Add all of the elements. + while (first != last) + { + this->insert(etl::move(*first++)); + } + } + } +#endif + private: // Disable copy construction. @@ -786,6 +860,20 @@ namespace etl this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + flat_set(flat_set&& other) + : etl::iflat_set(lookup, storage) + { + if (&other != this) + { + this->move_container(etl::move(other)); + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -831,6 +919,21 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + flat_set& operator = (flat_set&& rhs) + { + if (&rhs != this) + { + this->move_container(etl::move(rhs)); + } + + return *this; + } +#endif + private: typedef typename etl::iflat_set::value_type node_t; diff --git a/include/etl/icache.h b/include/etl/icache.h index 52b9995f..5ee5791c 100644 --- a/include/etl/icache.h +++ b/include/etl/icache.h @@ -36,8 +36,7 @@ SOFTWARE. #define __ETL_ICACHE__ #include "platform.h" -#include "function.h" -#include "nullptr.h" +#include "delegate.h" #include @@ -57,8 +56,8 @@ namespace etl ///************************************************************************ icache() : write_through(true), - p_read_store(nullptr), - p_write_store(nullptr) + read_store(nullptr), + write_store(nullptr) { } @@ -77,17 +76,17 @@ namespace etl ///************************************************************************ /// Sets the function that reads from the store. ///************************************************************************ - void set_read_function(etl::ifunction* p_read) + void set_read_function(etl::delegate reader_) { - p_read_store = p_read; + read_store = reader; } ///************************************************************************ /// Sets the function that writes to the store. ///************************************************************************ - void set_write_function(etl::ifunction* p_write) + void set_write_function(etl::delegate writer_) { - p_write_store = p_write; + write_store = writer; } ///************************************************************************ @@ -98,18 +97,18 @@ namespace etl write_through = write_through_; } - virtual const T& read(const TKey& key) const = 0; ///< Reads from the cache. May read from the store using p_read_store. - virtual void write(const TKey& key, const TValue& value) = 0; ///< Writes to the cache. May write to the store using p_write_store. + virtual const T& read(const TKey& key) const = 0; ///< Reads from the cache. May read from the store using read_store. + virtual void write(const TKey& key, const TValue& value) = 0; ///< Writes to the cache. May write to the store using write_store. virtual void flush() = 0; ///< The overridden function should write all changed values to the store. protected: - typedef ETL_PAIR key_value_t; + typedef ETL_OR_STD::pair key_value_t; bool write_through; ///< If true, the cache should write changed items back to the store immediately. If false then a flush() or destruct will be required. - etl::ifunction* p_read_store; ///< A pointer to the function that will read a value from the store into the cache. - etl::ifunction* p_write_store; ///< A pointer to the function that will write a value from the cache into the store. + etl::delegate* read_store; ///< A function that will read a value from the store into the cache. + etl::delegate* write_store; ///< A function that will write a value from the cache into the store. } } diff --git a/include/etl/map.h b/include/etl/map.h index b068888f..26b434c1 100755 --- a/include/etl/map.h +++ b/include/etl/map.h @@ -50,6 +50,7 @@ SOFTWARE. #include "type_traits.h" #include "parameter_type.h" #include "iterator.h" +#include "utility.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include @@ -473,6 +474,9 @@ namespace etl typedef TKeyCompare key_compare; typedef value_type& reference; typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif typedef value_type* pointer; typedef const value_type* const_pointer; typedef size_t size_type; @@ -481,7 +485,7 @@ namespace etl { public: - bool operator()(const value_type& lhs, const value_type& rhs) const + bool operator()(const_reference lhs, const_reference rhs) const { return (kcompare(lhs.first, rhs.first)); } @@ -1093,7 +1097,7 @@ namespace etl /// If asserts or exceptions are enabled, emits map_full if the map is already full. ///\param value The value to insert. //********************************************************************* - ETL_OR_STD::pair insert(const value_type& value) + ETL_OR_STD::pair insert(const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1112,13 +1116,39 @@ namespace etl return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the map. + /// If asserts or exceptions are enabled, emits map_full if the map is already full. + ///\param value The value to insert. + //********************************************************************* + ETL_OR_STD::pair insert(rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + bool inserted = false; + + ETL_ASSERT(!full(), ETL_ERROR(map_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + inserted = inserted_node == &node; + + // Insert node into tree and return iterator to new node location in tree + return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted); + } +#endif + //********************************************************************* /// Inserts a value to the map starting at the position recommended. /// If asserts or exceptions are enabled, emits map_full if the map is already full. ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator, const value_type& value) + iterator insert(iterator, const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1135,13 +1165,38 @@ namespace etl return iterator(*this, inserted_node); } +#if ETL_CPP11_SUPPORTED //********************************************************************* /// Inserts a value to the map starting at the position recommended. /// If asserts or exceptions are enabled, emits map_full if the map is already full. ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(const_iterator, const value_type& value) + iterator insert(iterator, rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + + ETL_ASSERT(!full(), ETL_ERROR(map_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + + // Insert node into tree and return iterator to new node location in tree + return iterator(*this, inserted_node); + } +#endif + + //********************************************************************* + /// Inserts a value to the map starting at the position recommended. + /// If asserts or exceptions are enabled, emits map_full if the map is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator, const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1158,6 +1213,31 @@ namespace etl return iterator(*this, inserted_node); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the map starting at the position recommended. + /// If asserts or exceptions are enabled, emits map_full if the map is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator, rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + + ETL_ASSERT(!full(), ETL_ERROR(map_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + + // Insert node into tree and return iterator to new node location in tree + return iterator(*this, inserted_node); + } +#endif + //********************************************************************* /// Inserts a range of values to the map. /// If asserts or exceptions are enabled, emits map_full if the map does not have enough free space. @@ -1232,6 +1312,29 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + imap& operator = (imap&& rhs) + { + // Skip if doing self assignment + if (this != &rhs) + { + this->clear(); + + typename etl::imap::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + this->insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + //************************************************************************* /// How to compare two key elements. //************************************************************************* @@ -1264,7 +1367,12 @@ namespace etl //************************************************************************* void initialise() { - erase(begin(), end()); + const_iterator item = begin(); + + while (item != end()) + { + item = erase(item); + } } private: @@ -1272,14 +1380,27 @@ namespace etl //************************************************************************* /// Allocate a Data_Node. //************************************************************************* - Data_Node& allocate_data_node(value_type value) + Data_Node& allocate_data_node(const_reference value) { Data_Node& node = *p_node_pool->allocate(); - ::new (&node.value) const value_type(value); + ::new (&node.value) value_type(value); ETL_INCREMENT_DEBUG_COUNT return node; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Allocate a Data_Node. + //************************************************************************* + Data_Node& allocate_data_node(rvalue_reference value) + { + Data_Node& node = *p_node_pool->allocate(); + ::new (&node.value) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + return node; + } +#endif + //************************************************************************* /// Destroy a Data_Node. //************************************************************************* @@ -2064,9 +2185,31 @@ namespace etl map(const map& other) : etl::imap(node_pool, MAX_SIZE) { - this->assign(other.cbegin(), other.cend()); + if (this != &other) + { + this->assign(other.cbegin(), other.cend()); + } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + map(map&& other) + : etl::imap(node_pool, MAX_SIZE) + { + if (this != &other) + { + typename etl::imap::iterator from = other.begin(); + + while (from != other.end()) + { + this->insert(etl::move(*from++)); + } + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -2113,6 +2256,29 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + map& operator = (map&& rhs) + { + // Skip if doing self assignment + if (this != &rhs) + { + this->clear(); + + typename etl::imap::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + this->insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + private: /// The pool of data nodes used for the map. diff --git a/include/etl/memory.h b/include/etl/memory.h index 39705ca1..ad6b6aee 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -266,7 +266,7 @@ namespace etl uninitialized_copy(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count) { TOutputIterator o_end = etl::copy(i_begin, i_end, o_begin); - count += int32_t(etl::distance(o_begin, o_end)); + count += int32_t(etl::distance(i_begin, i_end)); return o_end; } @@ -283,7 +283,7 @@ namespace etl { TOutputIterator o_end = etl::uninitialized_copy(i_begin, i_end, o_begin); - count += int32_t(etl::distance(o_begin, o_end)); + count += int32_t(etl::distance(i_begin, i_end)); return o_end; } @@ -366,6 +366,256 @@ namespace etl } #endif +#if ETL_CPP11_SUPPORTED +#if defined(ETL_NO_STL) || !ETL_CPP17_SUPPORTED + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) + { + return etl::move(i_begin, i_end, o_begin); + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) + { + typedef typename etl::iterator_traits::value_type value_type; + + TOutputIterator o_end = o_begin; + + while (i_begin != i_end) + { + ::new (static_cast(etl::addressof(*o_end))) value_type(etl::move(*i_begin)); + ++i_begin; + ++o_end; + } + + return o_end; + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count) + { + TOutputIterator o_end = etl::move(i_begin, i_end, o_begin); + count += int32_t(etl::distance(i_begin, i_end)); + + return o_end; + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count) + { + TOutputIterator o_end = etl::uninitialized_move(i_begin, i_end, o_begin); + + count += int32_t(etl::distance(i_begin, i_end)); + + return o_end; + } +#else + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) + { + return std::uninitialized_move(i_begin, i_end, o_begin); + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count) + { + count += int32_t(etl::distance(i_begin, i_end)); + + return std::uninitialized_move(i_begin, i_end, o_begin); + } +#endif +#else + // C++03 + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin) + { + // Move not supported. Defer to copy. + return std::uninitialized_copy(i_begin, i_end, o_begin); + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move(TInputIterator i_begin, TInputIterator i_end, TOutputIterator o_begin, TCounter& count) + { + count += int32_t(etl::distance(i_begin, i_end)); + + // Move not supported. Defer to copy. + return std::uninitialized_copy(i_begin, i_end, o_begin); + } +#endif + +#if ETL_CPP11_SUPPORTED +#if defined(ETL_NO_STL) || !ETL_CPP17_SUPPORTED + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin) + { + return etl::move(i_begin, i_begin + n, o_begin); + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin) + { + typedef typename etl::iterator_traits::value_type value_type; + + TOutputIterator o_end = o_begin; + + while (n-- != 0) + { + ::new (static_cast(etl::addressof(*o_end))) value_type(etl::move(*i_begin)); + ++i_begin; + ++o_end; + } + + return o_end; + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TCounter& count) + { + TOutputIterator o_end = etl::move(i_begin, i_begin + n, o_begin); + count += TCounter(n); + + return o_end; + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + typename etl::enable_if::value_type>::value, TOutputIterator>::type + uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TCounter& count) + { + TOutputIterator o_end = etl::uninitialized_move(i_begin, i_begin + n, o_begin); + + count += TCounter(n); + + return o_end; + } +#else + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin) + { + return std::uninitialized_move(i_begin, i_begin + n, o_begin); + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TCounter& count) + { + count += TCounter(n); + + return std::uninitialized_move(i_begin, i_begin + n, o_begin); + } +#endif +#else + // C++03 + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move_n + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin) + { + // Move not supported. Defer to copy. + return std::uninitialized_copy_n(i_begin, n, o_begin); + } + + //***************************************************************************** + /// Moves a range of objects to uninitialised memory. + /// Debug counter version. + /// https://en.cppreference.com/w/cpp/memory/uninitialized_move + ///\ingroup memory + //***************************************************************************** + template + TOutputIterator uninitialized_move_n(TInputIterator i_begin, TSize n, TOutputIterator o_begin, TCounter& count) + { + count += TCounter(n); + + // Move not supported. Defer to copy. + return std::uninitialized_copy_n(i_begin, n, o_begin); + } +#endif + #if defined(ETL_NO_STL) || !ETL_CPP17_SUPPORTED //***************************************************************************** /// Default initialises a range of objects to uninitialised memory. diff --git a/include/etl/multimap.h b/include/etl/multimap.h index 37ca3902..91586ea1 100644 --- a/include/etl/multimap.h +++ b/include/etl/multimap.h @@ -50,6 +50,7 @@ SOFTWARE. #include "type_traits.h" #include "parameter_type.h" #include "iterator.h" +#include "utility.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include @@ -635,6 +636,9 @@ namespace etl typedef TKeyCompare key_compare; typedef value_type& reference; typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif typedef value_type* pointer; typedef const value_type* const_pointer; typedef size_t size_type; @@ -643,7 +647,7 @@ namespace etl { public: - bool operator()(const value_type& lhs, const value_type& rhs) const + bool operator()(const_reference lhs, const_reference rhs) const { return (kcompare(lhs.first, rhs.first)); } @@ -1216,7 +1220,7 @@ namespace etl /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. ///\param value The value to insert. //********************************************************************* - iterator insert(const value_type& value) + iterator insert(const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1233,13 +1237,37 @@ namespace etl return iterator(*this, inserted_node); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the multimap. + /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. + ///\param value The value to insert. + //********************************************************************* + iterator insert(rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + + ETL_ASSERT(!full(), ETL_ERROR(multimap_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + + // Insert node into tree and return iterator to new node location in tree + return iterator(*this, inserted_node); + } +#endif + //********************************************************************* /// Inserts a value to the multimap starting at the position recommended. /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator /*position*/, const value_type& value) + iterator insert(iterator /*position*/, const_reference value) { // Ignore position provided and just do a normal insert return insert(value); @@ -1251,12 +1279,38 @@ namespace etl ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(const_iterator /*position*/, const value_type& value) + iterator insert(const_iterator /*position*/, const_reference value) { // Ignore position provided and just do a normal insert return insert(value); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the multimap starting at the position recommended. + /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator /*position*/, rvalue_reference value) + { + // Ignore position provided and just do a normal insert + return insert(etl::move(value)); + } + + //********************************************************************* + /// Inserts a value to the multimap starting at the position recommended. + /// If asserts or exceptions are enabled, emits map_full if the multimap is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator /*position*/, rvalue_reference value) + { + // Ignore position provided and just do a normal insert + return insert(etl::move(value)); + } +#endif + //********************************************************************* /// Inserts a range of values to the multimap. /// If asserts or exceptions are enabled, emits map_full if the multimap does not have enough free space. @@ -1331,6 +1385,29 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + imultimap& operator = (imultimap&& rhs) + { + // Skip if doing self assignment + if (this != &rhs) + { + this->clear(); + + iterator from = rhs.begin(); + + while (from != rhs.end()) + { + this->insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + //************************************************************************* /// How to compare two key elements. //************************************************************************* @@ -1363,7 +1440,12 @@ namespace etl //************************************************************************* void initialise() { - erase(begin(), end()); + const_iterator item = begin(); + + while (item != end()) + { + item = erase(item); + } } private: @@ -1371,7 +1453,7 @@ namespace etl //************************************************************************* /// Allocate a Data_Node. //************************************************************************* - Data_Node& allocate_data_node(value_type value) + Data_Node& allocate_data_node(const_reference value) { Data_Node& node = *p_node_pool->allocate(); ::new (&node.value) const value_type(value); @@ -1379,6 +1461,19 @@ namespace etl return node; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Allocate a Data_Node. + //************************************************************************* + Data_Node& allocate_data_node(rvalue_reference value) + { + Data_Node& node = *p_node_pool->allocate(); + ::new (&node.value) const value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + return node; + } +#endif + //************************************************************************* /// Destroy a Data_Node. //************************************************************************* @@ -1953,9 +2048,31 @@ namespace etl multimap(const multimap& other) : etl::imultimap(node_pool, MAX_SIZE) { - this->assign(other.cbegin(), other.cend()); + if (this != &other) + { + this->assign(other.cbegin(), other.cend()); + } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + multimap(multimap&& other) + : etl::imultimap(node_pool, MAX_SIZE) + { + if (this != &other) + { + typename etl::imultimap::iterator from = other.begin(); + + while (from != other.end()) + { + this->insert(etl::move(*from++)); + } + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -2002,6 +2119,26 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + multimap& operator = (multimap&& rhs) + { + if (this != &rhs) + { + typename etl::imultimap::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + this->insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + private: /// The pool of data nodes used for the multimap. diff --git a/include/etl/multiset.h b/include/etl/multiset.h index ffc63709..ae4eb7fc 100644 --- a/include/etl/multiset.h +++ b/include/etl/multiset.h @@ -49,6 +49,7 @@ SOFTWARE. #include "debug_count.h" #include "nullptr.h" #include "type_traits.h" +#include "utility.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include @@ -623,18 +624,23 @@ namespace etl /// A templated base for all etl::multiset types. ///\ingroup set //*************************************************************************** - template > + template > class imultiset : public etl::multiset_base { public: - typedef const T key_type; - typedef const T value_type; - typedef TCompare key_compare; - typedef TCompare value_compare; - typedef value_type& const_reference; - typedef value_type* const_pointer; - typedef size_t size_type; + typedef TKey key_type; + typedef TKey value_type; + typedef TCompare key_compare; + typedef TCompare value_compare; + typedef value_type& reference; + typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef size_t size_type; protected: @@ -652,7 +658,7 @@ namespace etl }; /// Defines the key value parameter type - typedef typename etl::parameter_type::type key_parameter_t; + typedef typename etl::parameter_type::type key_parameter_t; //************************************************************************* /// How to compare node elements. @@ -780,16 +786,31 @@ namespace etl return *this; } + reference operator *() + { + return imultiset::data_cast(p_node)->value; + } + const_reference operator *() const { return imultiset::data_cast(p_node)->value; } + pointer operator &() + { + return &(imultiset::data_cast(p_node)->value); + } + const_pointer operator &() const { return &(imultiset::data_cast(p_node)->value); } + pointer operator ->() + { + return &(imultiset::data_cast(p_node)->value); + } + const_pointer operator ->() const { return &(imultiset::data_cast(p_node)->value); @@ -813,6 +834,7 @@ namespace etl // Pointer to the current node for this iterator Node* p_node; }; + friend class iterator; //************************************************************************* @@ -923,6 +945,7 @@ namespace etl // Pointer to the current node for this iterator const Node* p_node; }; + friend class const_iterator; typedef typename etl::iterator_traits::difference_type difference_type; @@ -1062,7 +1085,7 @@ namespace etl /// Returns two iterators with bounding (lower bound, upper bound) the key /// provided //************************************************************************* - ETL_OR_STD::pair equal_range(const value_type& key) + ETL_OR_STD::pair equal_range(const_reference key) { return ETL_OR_STD::make_pair( iterator(*this, find_lower_node(root_node, key)), @@ -1073,7 +1096,7 @@ namespace etl /// Returns two const iterators with bounding (lower bound, upper bound) /// the key provided. //************************************************************************* - ETL_OR_STD::pair equal_range(const value_type& key) const + ETL_OR_STD::pair equal_range(const_reference key) const { return ETL_OR_STD::make_pair( const_iterator(*this, find_lower_node(root_node, key)), @@ -1181,7 +1204,7 @@ namespace etl /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. ///\param value The value to insert. //********************************************************************* - iterator insert(const value_type& value) + iterator insert(const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1198,17 +1221,29 @@ namespace etl return iterator(*this, inserted_node); } +#if ETL_CPP11_SUPPORTED //********************************************************************* - /// Inserts a value to the multiset starting at the position recommended. + /// Inserts a value to the multiset. /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. - ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator /*position*/, const value_type& value) + iterator insert(rvalue_reference value) { - // Ignore position provided and just do a normal insert - return insert(value); + // Default to no inserted node + Node* inserted_node = nullptr; + + ETL_ASSERT(!full(), ETL_ERROR(multiset_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + + // Insert node into tree and return iterator to new node location in tree + return iterator(*this, inserted_node); } +#endif //********************************************************************* /// Inserts a value to the multiset starting at the position recommended. @@ -1216,12 +1251,52 @@ namespace etl ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(const_iterator /*position*/, const value_type& value) + iterator insert(iterator /*position*/, const_reference value) { // Ignore position provided and just do a normal insert return insert(value); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the multiset starting at the position recommended. + /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(iterator /*position*/, rvalue_reference value) + { + // Ignore position provided and just do a normal insert + return insert(etl::move(value)); + } +#endif + + //********************************************************************* + /// Inserts a value to the multiset starting at the position recommended. + /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator /*position*/, const_reference value) + { + // Ignore position provided and just do a normal insert + return insert(value); + } + +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the multiset starting at the position recommended. + /// If asserts or exceptions are enabled, emits set_full if the multiset is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator /*position*/, rvalue_reference value) + { + // Ignore position provided and just do a normal insert + return insert(etl::move(value)); + } +#endif + //********************************************************************* /// Inserts a range of values to the multiset. /// If asserts or exceptions are enabled, emits set_full if the multiset does not have enough free space. @@ -1296,6 +1371,27 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + imultiset& operator = (imultiset&& rhs) + { + // Skip if doing self assignment + if (this != &rhs) + { + typename etl::imultiset::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + //************************************************************************* /// How to compare two key elements. //************************************************************************* @@ -1328,7 +1424,12 @@ namespace etl //************************************************************************* void initialise() { - erase(begin(), end()); + const_iterator item = begin(); + + while (item != end()) + { + item = erase(item); + } } private: @@ -1336,7 +1437,7 @@ namespace etl //************************************************************************* /// Allocate a Data_Node. //************************************************************************* - Data_Node& allocate_data_node(value_type value) + Data_Node& allocate_data_node(const_reference value) { Data_Node& node = *p_node_pool->allocate(); ::new ((void*)&node.value) value_type(value); @@ -1344,6 +1445,19 @@ namespace etl return node; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Allocate a Data_Node. + //************************************************************************* + Data_Node& allocate_data_node(rvalue_reference value) + { + Data_Node& node = *p_node_pool->allocate(); + ::new ((void*)&node.value) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + return node; + } +#endif + //************************************************************************* /// Destroy a Data_Node. //************************************************************************* @@ -1895,8 +2009,8 @@ namespace etl //************************************************************************* /// A templated multiset implementation that uses a fixed size buffer. //************************************************************************* - template > - class multiset : public etl::imultiset + template > + class multiset : public etl::imultiset { public: @@ -1906,7 +2020,7 @@ namespace etl /// Default constructor. //************************************************************************* multiset() - : etl::imultiset(node_pool, MAX_SIZE) + : etl::imultiset(node_pool, MAX_SIZE) { this->initialise(); } @@ -1915,11 +2029,30 @@ namespace etl /// Copy constructor. //************************************************************************* multiset(const multiset& other) - : etl::imultiset(node_pool, MAX_SIZE) + : etl::imultiset(node_pool, MAX_SIZE) { this->assign(other.cbegin(), other.cend()); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + multiset(multiset&& other) + : etl::imultiset(node_pool, MAX_SIZE) + { + if (this != &other) + { + typename etl::imultiset::iterator from = other.begin(); + + while (from != other.end()) + { + this->insert(etl::move(*from++)); + } + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -1928,7 +2061,7 @@ namespace etl //************************************************************************* template multiset(TIterator first, TIterator last) - : etl::imultiset(node_pool, MAX_SIZE) + : etl::imultiset(node_pool, MAX_SIZE) { this->assign(first, last); } @@ -1937,8 +2070,8 @@ namespace etl //************************************************************************* /// Constructor, from an initializer_list. //************************************************************************* - multiset(std::initializer_list::value_type> init) - : etl::imultiset(node_pool, MAX_SIZE) + multiset(std::initializer_list::value_type> init) + : etl::imultiset(node_pool, MAX_SIZE) { this->assign(init.begin(), init.end()); } @@ -1966,10 +2099,32 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + multiset& operator = (multiset&& rhs) + { + if (this != &rhs) + { + this->clear(); + + typename etl::imultiset::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + this->insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + private: /// The pool of data nodes used for the multiset. - etl::pool::Data_Node, MAX_SIZE> node_pool; + etl::pool::Data_Node, MAX_SIZE> node_pool; }; //*************************************************************************** @@ -1979,8 +2134,8 @@ namespace etl ///\return true if the arrays are equal, otherwise false ///\ingroup lookup //*************************************************************************** - template - bool operator ==(const etl::imultiset& lhs, const etl::imultiset& rhs) + template + bool operator ==(const etl::imultiset& lhs, const etl::imultiset& rhs) { return (lhs.size() == rhs.size()) && ETL_OR_STD::equal(lhs.begin(), lhs.end(), rhs.begin()); } @@ -1992,8 +2147,8 @@ namespace etl ///\return true if the arrays are not equal, otherwise false ///\ingroup lookup //*************************************************************************** - template - bool operator !=(const etl::imultiset& lhs, const etl::imultiset& rhs) + template + bool operator !=(const etl::imultiset& lhs, const etl::imultiset& rhs) { return !(lhs == rhs); } @@ -2005,8 +2160,8 @@ namespace etl ///\return true if the first list is lexicographically less than the /// second, otherwise false. //************************************************************************* - template - bool operator <(const etl::imultiset& lhs, const etl::imultiset& rhs) + template + bool operator <(const etl::imultiset& lhs, const etl::imultiset& rhs) { return ETL_OR_STD::lexicographical_compare(lhs.begin(), lhs.end(), @@ -2021,8 +2176,8 @@ namespace etl ///\return true if the first list is lexicographically greater than the /// second, otherwise false. //************************************************************************* - template - bool operator >(const etl::imultiset& lhs, const etl::imultiset& rhs) + template + bool operator >(const etl::imultiset& lhs, const etl::imultiset& rhs) { return (rhs < lhs); } @@ -2034,8 +2189,8 @@ namespace etl ///\return true if the first list is lexicographically less than or equal /// to the second, otherwise false. //************************************************************************* - template - bool operator <=(const etl::imultiset& lhs, const etl::imultiset& rhs) + template + bool operator <=(const etl::imultiset& lhs, const etl::imultiset& rhs) { return !(lhs > rhs); } @@ -2047,8 +2202,8 @@ namespace etl ///\return true if the first list is lexicographically greater than or /// equal to the second, otherwise false. //************************************************************************* - template - bool operator >=(const etl::imultiset& lhs, const etl::imultiset& rhs) + template + bool operator >=(const etl::imultiset& lhs, const etl::imultiset& rhs) { return !(lhs < rhs); } diff --git a/include/etl/optional.h b/include/etl/optional.h index dc2d5b58..958acf2f 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -138,6 +138,20 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Move constructor. + //*************************************************************************** + optional(optional&& other) + : valid(bool(other)) + { + if (valid) + { + ::new (storage.template get_address()) T(etl::move(other.value())); + } + } +#endif + //*************************************************************************** /// Constructor from value type. //*************************************************************************** @@ -147,6 +161,17 @@ namespace etl valid = true; } +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Constructor from value type. + //*************************************************************************** + optional(T&& value_) + { + ::new (storage.template get_address()) T(std::move(value_)); + valid = true; + } +#endif + //*************************************************************************** /// Destructor. //*************************************************************************** @@ -201,6 +226,37 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Assignment operator from optional. + //*************************************************************************** + optional& operator =(optional&& other) + { + if (this != &other) + { + if (valid && !bool(other)) + { + storage.template get_reference().~T(); + valid = false; + } + else if (bool(other)) + { + if (valid) + { + storage.template get_reference() = etl::move(other.value()); + } + else + { + ::new (storage.template get_address()) T(etl::move(other.value())); + valid = true; + } + } + } + + return *this; + } +#endif + //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** @@ -219,6 +275,26 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Assignment operator from value type. + //*************************************************************************** + optional& operator =(T&& value_) + { + if (valid) + { + storage.template get_reference() = etl::move(value_); + } + else + { + ::new (storage.template get_address()) T(etl::move(value_)); + valid = true; + } + + return *this; + } +#endif + //*************************************************************************** /// Pointer operator. //*************************************************************************** @@ -270,7 +346,7 @@ namespace etl //*************************************************************************** /// Bool conversion operator. //*************************************************************************** - explicit operator bool() const + ETL_EXPLICIT operator bool() const { return valid; } diff --git a/include/etl/packet.h b/include/etl/packet.h index 35390315..fbaf046b 100644 --- a/include/etl/packet.h +++ b/include/etl/packet.h @@ -36,6 +36,7 @@ SOFTWARE. #include "platform.h" #include "static_assert.h" #include "alignment.h" +#include "utility.h" #undef ETL_FILE #define ETL_FILE "38" @@ -58,6 +59,24 @@ namespace etl { public: + typedef TBase base_t; + +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Constructor that static asserts any types that do not conform to the max size and alignment. + //*************************************************************************** + template + explicit packet(T&& value) + { + typedef typename etl::types::type type; + + ETL_STATIC_ASSERT((etl::is_base_of::value), "Unsupported type"); + ETL_STATIC_ASSERT(sizeof(type) <= SIZE, "Unsupported size"); + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Unsupported alignment"); + + ::new (static_cast(data)) type(etl::forward(value)); + } +#else //*************************************************************************** /// Constructor that static asserts any types that do not conform to the max size and alignment. //*************************************************************************** @@ -70,6 +89,7 @@ namespace etl ::new (static_cast(data)) T(value); } +#endif //*************************************************************************** /// Destructor @@ -79,6 +99,26 @@ namespace etl static_cast(data)->~TBase(); } +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Assignment operator for type. + ///\param value The value to assign. + //*************************************************************************** + template + packet& operator =(T&& value) + { + typedef typename etl::types::type type; + + ETL_STATIC_ASSERT((etl::is_base_of::value), "Unsupported type"); + ETL_STATIC_ASSERT(sizeof(type) <= SIZE, "Unsupported size"); + ETL_STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Unsupported alignment"); + + static_cast(data)->~TBase(); + ::new (static_cast(data)) type(etl::forward(value)); + + return *this; + } +#else //*************************************************************************** /// Assignment operator for type. ///\param value The value to assign. @@ -95,6 +135,7 @@ namespace etl return *this; } +#endif //*************************************************************************** /// Get access to the contained object. diff --git a/include/etl/platform.h b/include/etl/platform.h index eaf3ae58..66291bd4 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -44,24 +44,12 @@ SOFTWARE. #endif #endif -// Undefine all of the macros. -#undef ETL_PLATFORM_16BIT -#undef ETL_PLATFORM_32BIT -#undef ETL_PLATFORM_64BIT -#undef ETL_CPP11_SUPPORTED -#undef ETL_CPP14_SUPPORTED -#undef ETL_CPP17_SUPPORTED -#undef ETL_NO_NULLPTR_SUPPORT -#undef ETL_NO_LARGE_CHAR_SUPPORT -#undef ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED -#undef ETL_STD_ATOMIC_SUPPORTED -#undef ETL_FORCE_EXPLICIT_STRING_CONVERSION_FROM_CHAR - // Determine the bit width of the platform. #define ETL_PLATFORM_16BIT (UINT16_MAX == UINTPTR_MAX) #define ETL_PLATFORM_32BIT (UINT32_MAX == UINTPTR_MAX) #define ETL_PLATFORM_64BIT (UINT64_MAX == UINTPTR_MAX) +// Include the user's profile definition. #include "etl_profile.h" #if defined(ETL_AUTO_DETERMINE_COMPILER_INFO) @@ -71,21 +59,38 @@ SOFTWARE. #include "profiles/determine_compiler_language_support.h" #endif +#if defined(ETL_FORCE_EXPLICIT_STRING_CONVERSION_FROM_CHAR) +#define ETL_EXPLICIT_STRING_FROM_CHAR explicit +#else +#define ETL_EXPLICIT_STRING_FROM_CHAR +#endif + // The macros below are dependent on the profile. +// C++11 #if ETL_CPP11_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP) #define ETL_CONSTEXPR constexpr #define ETL_CONST_OR_CONSTEXPR constexpr #define ETL_DELETE = delete #define ETL_NOEXCEPT noexcept #define ETL_NOEXCEPT_EXPR(expression) noexcept(expression) + #define ETL_EXPLICIT explicit #else #define ETL_CONSTEXPR #define ETL_CONST_OR_CONSTEXPR const #define ETL_DELETE #define ETL_NOEXCEPT #define ETL_NOEXCEPT_EXPR(expression) + #define ETL_EXPLICIT #endif +// C++14 +#if ETL_CPP14_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP) + #define ETL_CONSTEXPR14 constexpr +#else + #define ETL_CONSTEXPR14 +#endif + +// C++17 #if ETL_CPP17_SUPPORTED && !defined(ETL_FORCE_NO_ADVANCED_CPP) #define ETL_CONSTEXPR17 constexpr #define ETL_IF_CONSTEXPR constexpr @@ -96,12 +101,6 @@ SOFTWARE. #define ETL_NODISCARD #endif -#if defined(ETL_FORCE_EXPLICIT_STRING_CONVERSION_FROM_CHAR) - #define ETL_EXPLICIT_STRING_FROM_CHAR explicit -#else - #define ETL_EXPLICIT_STRING_FROM_CHAR -#endif - // Sort out namespaces for STL/No STL options. #include "private/choose_namespace.h" diff --git a/include/etl/queue.h b/include/etl/queue.h index f669be1d..c89b1cf7 100644 --- a/include/etl/queue.h +++ b/include/etl/queue.h @@ -47,6 +47,7 @@ SOFTWARE. #include "parameter_type.h" #include "memory_model.h" #include "integral_limits.h" +#include "utility.h" #undef ETL_FILE #define ETL_FILE "13" @@ -247,7 +248,6 @@ namespace etl { private: - typedef typename etl::parameter_type::type parameter_t; typedef typename etl::queue_base base_t; public: @@ -255,6 +255,9 @@ namespace etl typedef T value_type; ///< The type stored in the queue. typedef T& reference; ///< A reference to the type used in the queue. typedef const T& const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference;///< An rvalue reference to the type used in the queue. +#endif typedef T* pointer; ///< A pointer to the type used in the queue. typedef const T* const_pointer; ///< A const pointer to the type used in the queue. typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. @@ -309,7 +312,7 @@ namespace etl /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full. ///\param value The value to push to the queue. //************************************************************************* - void push(parameter_t value) + void push(const_reference value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(queue_full)); @@ -318,6 +321,22 @@ namespace etl add_in(); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Adds a value to the queue. + /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full. + ///\param value The value to push to the queue. + //************************************************************************* + void push(rvalue_reference value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(!full(), ETL_ERROR(queue_full)); +#endif + ::new (&p_buffer[in]) T(etl::move(value)); + add_in(); + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_QUEUE_FORCE_CPP03) //************************************************************************* /// Constructs a value in the queue 'in place'. @@ -468,6 +487,22 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Assignment operator. + //************************************************************************* + iqueue& operator = (iqueue&& rhs) + { + if (&rhs != this) + { + clear(); + move_clone(rhs); + } + + return *this; + } +#endif + protected: //************************************************************************* @@ -486,6 +521,24 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Make this a moved clone of the supplied queue + //************************************************************************* + void move_clone(iqueue&& other) + { + clear(); + + size_type index = other.out; + + for (size_type i = 0; i < other.size(); ++i) + { + push(etl::move(other.p_buffer[index])); + index = (index == (CAPACITY - 1)) ? 0 : index + 1; + } + } +#endif + //************************************************************************* /// The constructor that is called from derived classes. //************************************************************************* @@ -558,6 +611,17 @@ namespace etl base_t::clone(rhs); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Copy constructor + //************************************************************************* + queue(queue&& rhs) + : base_t(reinterpret_cast(&buffer[0]), SIZE) + { + base_t::move_clone(std::move(rhs)); + } +#endif + //************************************************************************* /// Destructor. //************************************************************************* @@ -579,9 +643,24 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + queue& operator = (queue&& rhs) + { + if (&rhs != this) + { + base_t::move_clone(rhs); + } + + return *this; + } +#endif + private: - /// The uninitialised buffer of T used in the stack. + /// The uninitialised buffer of T used in the queue. typename etl::aligned_storage::value>::type buffer[SIZE]; }; } diff --git a/include/etl/queue_mpmc_mutex.h b/include/etl/queue_mpmc_mutex.h index b8d220d1..004684a6 100644 --- a/include/etl/queue_mpmc_mutex.h +++ b/include/etl/queue_mpmc_mutex.h @@ -45,7 +45,6 @@ SOFTWARE. #include "parameter_type.h" #include "memory_model.h" #include "integral_limits.h" - #include "utility.h" #undef ETL_FILE @@ -139,7 +138,6 @@ namespace etl { private: - typedef typename etl::parameter_type::type parameter_t; typedef etl::queue_mpmc_mutex_base base_t; public: @@ -147,6 +145,9 @@ namespace etl typedef T value_type; ///< The type stored in the queue. typedef T& reference; ///< A reference to the type used in the queue. typedef const T& const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference;///< An rvalue reference to the type used in the queue. +#endif typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. using base_t::write_index; @@ -158,7 +159,7 @@ namespace etl //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push(parameter_t value) + bool push(const_reference value) { access.lock(); @@ -169,6 +170,22 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push(rvalue_reference value) + { + access.lock(); + + bool result = push_implementation(etl::move(value)); + + access.unlock(); + + return result; + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03) //************************************************************************* /// Constructs a value in the queue 'in place'. @@ -265,6 +282,20 @@ namespace etl return result; } + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop(rvalue_reference value) + { + access.lock(); + + bool result = pop_implementation(etl::move(value)); + + access.unlock(); + + return result; + } + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -366,7 +397,7 @@ namespace etl //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push_implementation(parameter_t value) + bool push_implementation(const_reference value) { if (current_size != MAX_SIZE) { @@ -383,6 +414,29 @@ namespace etl return false; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push_implementation(rvalue_reference value) + { + if (current_size != MAX_SIZE) + { + ::new (&p_buffer[write_index]) T(etl::move(value)); + + write_index = get_next_index(write_index, MAX_SIZE); + + ++current_size; + + return true; + } + + // Queue is full. + return false; + } +#endif + + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03) //************************************************************************* /// Constructs a value in the queue 'in place'. @@ -511,6 +565,29 @@ namespace etl return true; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop_implementation(rvalue_reference value) + { + if (current_size == 0) + { + // Queue is empty + return false; + } + + value = etl::move(p_buffer[read_index]); + p_buffer[read_index].~T(); + + read_index = get_next_index(read_index, MAX_SIZE); + + --current_size; + + return true; + } +#endif + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -581,8 +658,13 @@ namespace etl private: - queue_mpmc_mutex(const queue_mpmc_mutex&); - queue_mpmc_mutex& operator = (const queue_mpmc_mutex&); + queue_mpmc_mutex(const queue_mpmc_mutex&) ETL_DELETE; + queue_mpmc_mutex& operator = (const queue_mpmc_mutex&) ETL_DELETE; + +#if ETL_CPP11_SUPPORTED + queue_mpmc_mutex(queue_mpmc_mutex&&) = delete; + queue_mpmc_mutex& operator = (queue_mpmc_mutex&&) = delete; +#endif /// The uninitialised buffer of T used in the queue_mpmc_mutex. typename etl::aligned_storage::value>::type buffer[MAX_SIZE]; diff --git a/include/etl/queue_spsc_atomic.h b/include/etl/queue_spsc_atomic.h index f0490385..a50176c6 100644 --- a/include/etl/queue_spsc_atomic.h +++ b/include/etl/queue_spsc_atomic.h @@ -42,6 +42,7 @@ SOFTWARE. #include "atomic.h" #include "memory_model.h" #include "integral_limits.h" +#include "utility.h" #undef ETL_FILE #define ETL_FILE "47" @@ -190,7 +191,6 @@ namespace etl { private: - typedef typename etl::parameter_type::type parameter_t; typedef typename etl::queue_spsc_atomic_base base_t; public: @@ -198,6 +198,9 @@ namespace etl typedef T value_type; ///< The type stored in the queue. typedef T& reference; ///< A reference to the type used in the queue. typedef const T& const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference;///< An rvalue_reference to the type used in the queue. +#endif typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. using base_t::write; @@ -208,7 +211,7 @@ namespace etl //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push(parameter_t value) + bool push(const_reference value) { size_type write_index = write.load(etl::memory_order_relaxed); size_type next_index = get_next_index(write_index, RESERVED); @@ -226,6 +229,29 @@ namespace etl return false; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push(rvalue_reference value) + { + size_type write_index = write.load(etl::memory_order_relaxed); + size_type next_index = get_next_index(write_index, RESERVED); + + if (next_index != read.load(etl::memory_order_acquire)) + { + ::new (&p_buffer[write_index]) T(etl::move(value)); + + write.store(next_index, etl::memory_order_release); + + return true; + } + + // Queue is full. + return false; + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_QUEUE_ATOMIC_FORCE_CPP03) //************************************************************************* /// Constructs a value in the queue 'in place'. @@ -366,6 +392,31 @@ namespace etl return true; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop(rvalue_reference value) + { + size_type read_index = read.load(etl::memory_order_relaxed); + + if (read_index == write.load(etl::memory_order_acquire)) + { + // Queue is empty + return false; + } + + size_type next_index = get_next_index(read_index, RESERVED); + + value = etl::move(p_buffer[read_index]); + p_buffer[read_index].~T(); + + read.store(next_index, etl::memory_order_release); + + return true; + } +#endif + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -415,8 +466,13 @@ namespace etl private: // Disable copy construction and assignment. - iqueue_spsc_atomic(const iqueue_spsc_atomic&); - iqueue_spsc_atomic& operator =(const iqueue_spsc_atomic&); + iqueue_spsc_atomic(const iqueue_spsc_atomic&) ETL_DELETE; + iqueue_spsc_atomic& operator =(const iqueue_spsc_atomic&) ETL_DELETE; + +#if ETL_CPP11_SUPPORTED + iqueue_spsc_atomic(iqueue_spsc_atomic&&) = delete; + iqueue_spsc_atomic& operator =(iqueue_spsc_atomic&&) = delete; +#endif T* p_buffer; ///< The internal buffer. }; diff --git a/include/etl/queue_spsc_isr.h b/include/etl/queue_spsc_isr.h index aadd8420..408d4985 100644 --- a/include/etl/queue_spsc_isr.h +++ b/include/etl/queue_spsc_isr.h @@ -41,7 +41,6 @@ SOFTWARE. #include "parameter_type.h" #include "memory_model.h" #include "integral_limits.h" - #include "utility.h" #undef ETL_FILE @@ -52,10 +51,6 @@ namespace etl template class queue_spsc_isr_base { - protected: - - typedef typename etl::parameter_type::type parameter_t; - public: /// The type used for determining the size of queue. @@ -64,15 +59,28 @@ namespace etl typedef T value_type; ///< The type stored in the queue. typedef T& reference; ///< A reference to the type used in the queue. typedef const T& const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference;///< An rvalue reference to the type used in the queue. +#endif //************************************************************************* /// Push a value to the queue from an ISR. //************************************************************************* - bool push_from_isr(parameter_t value) + bool push_from_isr(const_reference value) { return push_implementation(value); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue from an ISR. + //************************************************************************* + bool push_from_isr(rvalue_reference value) + { + return push_implementation(etl::move(value)); + } +#endif + //************************************************************************* /// Constructs a value in the queue 'in place'. /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full. @@ -94,6 +102,16 @@ namespace etl return pop_implementation(value); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue from an ISR + //************************************************************************* + bool pop_from_isr(rvalue_reference value) + { + return pop_implementation(etl::move(value)); + } +#endif + //************************************************************************* /// Pop a value from the queue from an ISR, and discard. //************************************************************************* @@ -179,7 +197,7 @@ namespace etl //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push_implementation(parameter_t value) + bool push_implementation(const_reference value) { if (current_size != MAX_SIZE) { @@ -196,6 +214,28 @@ namespace etl return false; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push_implementation(rvalue_reference value) + { + if (current_size != MAX_SIZE) + { + ::new (&p_buffer[write_index]) T(etl::move(value)); + + write_index = get_next_index(write_index, MAX_SIZE); + + ++current_size; + + return true; + } + + // Queue is full. + return false; + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_QUEUE_ISR_FORCE_CPP03) //************************************************************************* /// Constructs a value in the queue 'in place'. @@ -331,6 +371,29 @@ namespace etl return true; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop_implementation(rvalue_reference value) + { + if (current_size == 0) + { + // Queue is empty + return false; + } + + value = etl::move(p_buffer[read_index]); + p_buffer[read_index].~T(); + + read_index = get_next_index(read_index, MAX_SIZE); + + --current_size; + + return true; + } +#endif + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -407,19 +470,21 @@ namespace etl private: typedef queue_spsc_isr_base base_t; - typedef typename base_t::parameter_t parameter_t; public: - typedef typename base_t::value_type value_type; ///< The type stored in the queue. - typedef typename base_t::reference reference; ///< A reference to the type used in the queue. - typedef typename base_t::const_reference const_reference; ///< A const reference to the type used in the queue. - typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. + typedef typename base_t::value_type value_type; ///< The type stored in the queue. + typedef typename base_t::reference reference; ///< A reference to the type used in the queue. + typedef typename base_t::const_reference const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef typename base_t::rvalue_reference rvalue_reference;///< A const reference to the type used in the queue. +#endif + typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push(parameter_t value) + bool push(const_reference value) { TAccess::lock(); @@ -430,6 +495,22 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push(rvalue_reference value) + { + TAccess::lock(); + + bool result = this->push_implementation(etl::move(value)); + + TAccess::unlock(); + + return result; + } +#endif + //************************************************************************* /// Constructs a value in the queue 'in place'. /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full. @@ -526,6 +607,22 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop(rvalue_reference value) + { + TAccess::lock(); + + bool result = this->pop_implementation(etl::move(value)); + + TAccess::unlock(); + + return result; + } +#endif + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -624,8 +721,13 @@ namespace etl private: // Disable copy construction and assignment. - iqueue_spsc_isr(const iqueue_spsc_isr&); - iqueue_spsc_isr& operator =(const iqueue_spsc_isr&); + iqueue_spsc_isr(const iqueue_spsc_isr&) ETL_DELETE; + iqueue_spsc_isr& operator =(const iqueue_spsc_isr&) ETL_DELETE; + +#if ETL_CPP11_SUPPORTED + iqueue_spsc_isr(iqueue_spsc_isr&&) = delete; + iqueue_spsc_isr& operator =(iqueue_spsc_isr&&) = delete; +#endif TAccess access; ///< The object that locks/unlocks interrupts. }; @@ -675,6 +777,11 @@ namespace etl queue_spsc_isr(const queue_spsc_isr&); queue_spsc_isr& operator = (const queue_spsc_isr&); +#if ETL_CPP11_SUPPORTED + queue_spsc_isr(queue_spsc_isr&&) = delete; + queue_spsc_isr& operator =(queue_spsc_isr&&) = delete; +#endif + /// The uninitialised buffer of T used in the queue_spsc_isr. typename etl::aligned_storage::value>::type buffer[MAX_SIZE]; }; diff --git a/include/etl/queue_spsc_locked.h b/include/etl/queue_spsc_locked.h index 75053fd1..c0e4dca0 100644 --- a/include/etl/queue_spsc_locked.h +++ b/include/etl/queue_spsc_locked.h @@ -42,21 +42,16 @@ SOFTWARE. #include "memory_model.h" #include "integral_limits.h" #include "function.h" - #include "utility.h" #undef ETL_FILE -#define ETL_FILE "46" +#define ETL_FILE "54" namespace etl { template - class queue_spsc_isr_base + class iqueue_spsc_locked_base { - protected: - - typedef typename etl::parameter_type::type parameter_t; - public: /// The type used for determining the size of queue. @@ -65,15 +60,28 @@ namespace etl typedef T value_type; ///< The type stored in the queue. typedef T& reference; ///< A reference to the type used in the queue. typedef const T& const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference;///< An rvalue reference to the type used in the queue. +#endif //************************************************************************* /// Push a value to the queue from an ISR. //************************************************************************* - bool push_from_unlocked(parameter_t value) + bool push_from_unlocked(const_reference value) { return push_implementation(value); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue from an ISR. + //************************************************************************* + bool push_from_unlocked(rvalue_reference value) + { + return push_implementation(etl::move(value)); + } +#endif + //************************************************************************* /// Constructs a value in the queue 'in place'. /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full. @@ -95,6 +103,16 @@ namespace etl return pop_implementation(value); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue from an ISR + //************************************************************************* + bool pop_from_unlocked(rvalue_reference value) + { + return pop_implementation(etl::move(value)); + } +#endif + //************************************************************************* /// Pop a value from the queue from an ISR, and discard. //************************************************************************* @@ -168,7 +186,7 @@ namespace etl protected: - queue_spsc_isr_base(T* p_buffer_, size_type max_size_) + iqueue_spsc_locked_base(T* p_buffer_, size_type max_size_) : p_buffer(p_buffer_), write_index(0), read_index(0), @@ -180,7 +198,7 @@ namespace etl //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push_implementation(parameter_t value) + bool push_implementation(const_reference value) { if (current_size != MAX_SIZE) { @@ -197,6 +215,28 @@ namespace etl return false; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push_implementation(rvalue_reference value) + { + if (current_size != MAX_SIZE) + { + ::new (&p_buffer[write_index]) T(etl::move(value)); + + write_index = get_next_index(write_index, MAX_SIZE); + + ++current_size; + + return true; + } + + // Queue is full. + return false; + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_QUEUE_LOCKED_FORCE_CPP03) //************************************************************************* /// Constructs a value in the queue 'in place'. @@ -332,6 +372,29 @@ namespace etl return true; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop_implementation(rvalue_reference value) + { + if (current_size == 0) + { + // Queue is empty + return false; + } + + value = etl::move(p_buffer[read_index]); + p_buffer[read_index].~T(); + + read_index = get_next_index(read_index, MAX_SIZE); + + --current_size; + + return true; + } +#endif + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -380,12 +443,12 @@ namespace etl //************************************************************************* #if defined(ETL_POLYMORPHIC_SPSC_QUEUE_ISR) || defined(ETL_POLYMORPHIC_CONTAINERS) public: - virtual ~queue_spsc_isr_base() + virtual ~iqueue_spsc_locked_base() { } #else protected: - ~queue_spsc_isr_base() + ~iqueue_spsc_locked_base() { } #endif @@ -399,24 +462,26 @@ namespace etl /// \tparam T The type of value that the queue_spsc_locked holds. //*************************************************************************** template - class iqueue_spsc_locked : public queue_spsc_isr_base + class iqueue_spsc_locked : public iqueue_spsc_locked_base { private: - typedef queue_spsc_isr_base base_t; - typedef typename base_t::parameter_t parameter_t; + typedef iqueue_spsc_locked_base base_t; public: - typedef typename base_t::value_type value_type; ///< The type stored in the queue. - typedef typename base_t::reference reference; ///< A reference to the type used in the queue. - typedef typename base_t::const_reference const_reference; ///< A const reference to the type used in the queue. - typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. + typedef typename base_t::value_type value_type; ///< The type stored in the queue. + typedef typename base_t::reference reference; ///< A reference to the type used in the queue. + typedef typename base_t::const_reference const_reference; ///< A const reference to the type used in the queue. +#if ETL_CPP11_SUPPORTED + typedef typename base_t::rvalue_reference rvalue_reference;///< An rvalue reference to the type used in the queue. +#endif + typedef typename base_t::size_type size_type; ///< The type used for determining the size of the queue. //************************************************************************* /// Push a value to the queue. //************************************************************************* - bool push(parameter_t value) + bool push(const_reference value) { lock(); @@ -427,6 +492,22 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Push a value to the queue. + //************************************************************************* + bool push(rvalue_reference value) + { + lock(); + + bool result = this->push_implementation(etl::move(value)); + + unlock(); + + return result; + } +#endif + //************************************************************************* /// Constructs a value in the queue 'in place'. /// If asserts or exceptions are enabled, throws an etl::queue_full if the queue if already full. @@ -523,6 +604,22 @@ namespace etl return result; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Pop a value from the queue. + //************************************************************************* + bool pop(rvalue_reference value) + { + lock(); + + bool result = this->pop_implementation(etl::move(value)); + + unlock(); + + return result; + } +#endif + //************************************************************************* /// Pop a value from the queue and discard. //************************************************************************* @@ -623,8 +720,13 @@ namespace etl private: // Disable copy construction and assignment. - iqueue_spsc_locked(const iqueue_spsc_locked&); - iqueue_spsc_locked& operator =(const iqueue_spsc_locked&); + iqueue_spsc_locked(const iqueue_spsc_locked&) ETL_DELETE; + iqueue_spsc_locked& operator =(const iqueue_spsc_locked&) ETL_DELETE; + +#if ETL_CPP11_SUPPORTED + iqueue_spsc_locked(iqueue_spsc_locked&&) = delete; + iqueue_spsc_locked& operator =(iqueue_spsc_locked&&) = delete; +#endif const etl::ifunction& lock; ///< The callback that locks interrupts. const etl::ifunction& unlock; ///< The callback that unlocks interrupts. @@ -673,8 +775,13 @@ namespace etl private: - queue_spsc_locked(const queue_spsc_locked&); - queue_spsc_locked& operator = (const queue_spsc_locked&); + queue_spsc_locked(const queue_spsc_locked&) ETL_DELETE; + queue_spsc_locked& operator = (const queue_spsc_locked&) ETL_DELETE; + +#if ETL_CPP11_SUPPORTED + queue_spsc_locked(queue_spsc_locked&&) = delete; + queue_spsc_locked& operator =(queue_spsc_locked&&) = delete; +#endif /// The uninitialised buffer of T used in the queue_spsc_locked. typename etl::aligned_storage::value>::type buffer[MAX_SIZE]; diff --git a/include/etl/set.h b/include/etl/set.h index 92b24109..31674b3d 100755 --- a/include/etl/set.h +++ b/include/etl/set.h @@ -45,6 +45,7 @@ SOFTWARE. #include "type_traits.h" #include "parameter_type.h" #include "iterator.h" +#include "utility.h" #include "algorithm.h" #include "iterator.h" @@ -457,18 +458,23 @@ namespace etl /// A templated base for all etl::set types. ///\ingroup set //*************************************************************************** - template > + template > class iset : public etl::set_base { public: - typedef const T key_type; - typedef const T value_type; - typedef TCompare key_compare; - typedef TCompare value_compare; - typedef value_type& const_reference; - typedef value_type* const_pointer; - typedef size_t size_type; + typedef TKey key_type; + typedef TKey value_type; + typedef TCompare key_compare; + typedef TCompare value_compare; + typedef value_type& reference; + typedef const value_type& const_reference; +#if ETL_CPP11_SUPPORTED + typedef value_type&& rvalue_reference; +#endif + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef size_t size_type; protected: @@ -486,7 +492,7 @@ namespace etl }; /// Defines the key value parameter type - typedef typename etl::parameter_type::type key_parameter_t; + typedef typename etl::parameter_type::type key_parameter_t; //************************************************************************* /// How to compare node elements. @@ -500,6 +506,7 @@ namespace etl { return compare(node.value, key); } + bool node_comp(key_parameter_t key, const Data_Node& node) const { @@ -616,16 +623,31 @@ namespace etl return *this; } + reference operator *() + { + return iset::data_cast(p_node)->value; + } + const_reference operator *() const { return iset::data_cast(p_node)->value; } + pointer operator &() + { + return &(iset::data_cast(p_node)->value); + } + const_pointer operator &() const { return &(iset::data_cast(p_node)->value); } + pointer operator ->() + { + return &(iset::data_cast(p_node)->value); + } + const_pointer operator ->() const { return &(iset::data_cast(p_node)->value); @@ -771,6 +793,7 @@ namespace etl //************************************************************************* iset& operator = (const iset& rhs) { + // Skip if doing self assignment if (this != &rhs) { assign(rhs.cbegin(), rhs.cend()); @@ -779,6 +802,27 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + iset& operator = (iset&& rhs) + { + // Skip if doing self assignment + if (this != &rhs) + { + typename etl::iset::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + //************************************************************************* /// Gets the beginning of the set. //************************************************************************* @@ -911,7 +955,7 @@ namespace etl /// Returns two iterators with bounding (lower bound, upper bound) the /// value provided //************************************************************************* - ETL_OR_STD::pair equal_range(const value_type& value) + ETL_OR_STD::pair equal_range(const_reference value) { return ETL_OR_STD::make_pair( iterator(*this, find_lower_node(root_node, value)), @@ -922,7 +966,7 @@ namespace etl /// Returns two const iterators with bounding (lower bound, upper bound) /// the value provided. //************************************************************************* - ETL_OR_STD::pair equal_range(const value_type& value) const + ETL_OR_STD::pair equal_range(const_reference value) const { return ETL_OR_STD::make_pair( const_iterator(*this, find_lower_node(root_node, value)), @@ -1015,7 +1059,7 @@ namespace etl /// If asserts or exceptions are enabled, emits set_full if the set is already full. ///\param value The value to insert. //********************************************************************* - ETL_OR_STD::pair insert(value_type& value) + ETL_OR_STD::pair insert(const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1034,13 +1078,39 @@ namespace etl return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the set. + /// If asserts or exceptions are enabled, emits set_full if the set is already full. + ///\param value The value to insert. + //********************************************************************* + ETL_OR_STD::pair insert(rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + bool inserted = false; + + ETL_ASSERT(!full(), ETL_ERROR(set_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + inserted = inserted_node == &node; + + // Insert node into tree and return iterator to new node location in tree + return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted); + } +#endif + //********************************************************************* /// Inserts a value to the set starting at the position recommended. /// If asserts or exceptions are enabled, emits set_full if the set is already full. ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(iterator, value_type& value) + iterator insert(iterator, const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1057,13 +1127,38 @@ namespace etl return iterator(*this, inserted_node); } +#if ETL_CPP11_SUPPORTED //********************************************************************* /// Inserts a value to the set starting at the position recommended. /// If asserts or exceptions are enabled, emits set_full if the set is already full. ///\param position The position that would precede the value to insert. ///\param value The value to insert. //********************************************************************* - iterator insert(const_iterator, value_type& value) + iterator insert(iterator, rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + + ETL_ASSERT(!full(), ETL_ERROR(set_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + + // Insert node into tree and return iterator to new node location in tree + return iterator(*this, inserted_node); + } +#endif + + //********************************************************************* + /// Inserts a value to the set starting at the position recommended. + /// If asserts or exceptions are enabled, emits set_full if the set is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator, const_reference value) { // Default to no inserted node Node* inserted_node = nullptr; @@ -1080,6 +1175,31 @@ namespace etl return iterator(*this, inserted_node); } +#if ETL_CPP11_SUPPORTED + //********************************************************************* + /// Inserts a value to the set starting at the position recommended. + /// If asserts or exceptions are enabled, emits set_full if the set is already full. + ///\param position The position that would precede the value to insert. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator, rvalue_reference value) + { + // Default to no inserted node + Node* inserted_node = nullptr; + + ETL_ASSERT(!full(), ETL_ERROR(set_full)); + + // Get next available free node + Data_Node& node = allocate_data_node(etl::move(value)); + + // Obtain the inserted node (might be nullptr if node was a duplicate) + inserted_node = insert_node(root_node, node); + + // Insert node into tree and return iterator to new node location in tree + return iterator(*this, inserted_node); + } +#endif + //********************************************************************* /// Inserts a range of values to the set. /// If asserts or exceptions are enabled, emits set_full if the set does not have enough free space. @@ -1172,7 +1292,12 @@ namespace etl //************************************************************************* void initialise() { - erase(begin(), end()); + const_iterator item = begin(); + + while (item != end()) + { + item = erase(item); + } } private: @@ -1180,7 +1305,7 @@ namespace etl //************************************************************************* /// Allocate a Data_Node. //************************************************************************* - Data_Node& allocate_data_node(value_type value) + Data_Node& allocate_data_node(const_reference value) { Data_Node& node = *p_node_pool->allocate(); ::new ((void*)&node.value) value_type(value); @@ -1188,6 +1313,19 @@ namespace etl return node; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Allocate a Data_Node. + //************************************************************************* + Data_Node& allocate_data_node(rvalue_reference value) + { + Data_Node& node = *p_node_pool->allocate(); + ::new ((void*)&node.value) value_type(etl::move(value)); + ETL_INCREMENT_DEBUG_COUNT + return node; + } +#endif + //************************************************************************* /// Destroy a Data_Node. //************************************************************************* @@ -1950,8 +2088,8 @@ namespace etl //************************************************************************* /// A templated set implementation that uses a fixed size buffer. //************************************************************************* - template > - class set : public etl::iset + template > + class set : public etl::iset { public: @@ -1961,7 +2099,7 @@ namespace etl /// Default constructor. //************************************************************************* set() - : etl::iset(node_pool, MAX_SIZE) + : etl::iset(node_pool, MAX_SIZE) { this->initialise(); } @@ -1970,11 +2108,33 @@ namespace etl /// Copy constructor. //************************************************************************* set(const set& other) - : etl::iset(node_pool, MAX_SIZE) + : etl::iset(node_pool, MAX_SIZE) { - this->assign(other.cbegin(), other.cend()); + if (this != &other) + { + this->assign(other.cbegin(), other.cend()); + } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move constructor. + //************************************************************************* + set(set&& other) + : etl::iset(node_pool, MAX_SIZE) + { + if (this != &other) + { + typename etl::iset::iterator from = other.begin(); + + while (from != other.end()) + { + this->insert(etl::move(*from++)); + } + } + } +#endif + //************************************************************************* /// Constructor, from an iterator range. ///\tparam TIterator The iterator type. @@ -1983,7 +2143,7 @@ namespace etl //************************************************************************* template set(TIterator first, TIterator last) - : etl::iset(node_pool, MAX_SIZE) + : etl::iset(node_pool, MAX_SIZE) { this->assign(first, last); } @@ -1992,8 +2152,8 @@ namespace etl //************************************************************************* /// Constructor, from an initializer_list. //************************************************************************* - set(std::initializer_list::value_type> init) - : etl::iset(node_pool, MAX_SIZE) + set(std::initializer_list::value_type> init) + : etl::iset(node_pool, MAX_SIZE) { this->assign(init.begin(), init.end()); } @@ -2021,10 +2181,31 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + set& operator = (set&& rhs) + { + // Skip if doing self assignment + if (this != &rhs) + { + typename etl::iset::iterator from = rhs.begin(); + + while (from != rhs.end()) + { + this->insert(etl::move(*from++)); + } + } + + return *this; + } +#endif + private: /// The pool of data nodes used for the set. - etl::pool::Data_Node, MAX_SIZE> node_pool; + etl::pool::Data_Node, MAX_SIZE> node_pool; }; //*************************************************************************** @@ -2034,8 +2215,8 @@ namespace etl ///\return true if the arrays are equal, otherwise false ///\ingroup lookup //*************************************************************************** - template - bool operator ==(const etl::iset& lhs, const etl::iset& rhs) + template + bool operator ==(const etl::iset& lhs, const etl::iset& rhs) { return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin()); } @@ -2047,8 +2228,8 @@ namespace etl ///\return true if the arrays are not equal, otherwise false ///\ingroup lookup //*************************************************************************** - template - bool operator !=(const etl::iset& lhs, const etl::iset& rhs) + template + bool operator !=(const etl::iset& lhs, const etl::iset& rhs) { return !(lhs == rhs); } @@ -2060,8 +2241,8 @@ namespace etl ///\return true if the first list is lexicographically less than the /// second, otherwise false. //************************************************************************* - template - bool operator <(const etl::iset& lhs, const etl::iset& rhs) + template + bool operator <(const etl::iset& lhs, const etl::iset& rhs) { return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } @@ -2073,8 +2254,8 @@ namespace etl ///\return true if the first list is lexicographically greater than the /// second, otherwise false. //************************************************************************* - template - bool operator >(const etl::iset& lhs, const etl::iset& rhs) + template + bool operator >(const etl::iset& lhs, const etl::iset& rhs) { return (rhs < lhs); } @@ -2086,8 +2267,8 @@ namespace etl ///\return true if the first list is lexicographically less than or equal /// to the second, otherwise false. //************************************************************************* - template - bool operator <=(const etl::iset& lhs, const etl::iset& rhs) + template + bool operator <=(const etl::iset& lhs, const etl::iset& rhs) { return !(lhs > rhs); } @@ -2099,8 +2280,8 @@ namespace etl ///\return true if the first list is lexicographically greater than or /// equal to the second, otherwise false. //************************************************************************* - template - bool operator >=(const etl::iset& lhs, const etl::iset& rhs) + template + bool operator >=(const etl::iset& lhs, const etl::iset& rhs) { return !(lhs < rhs); } diff --git a/include/etl/stack.h b/include/etl/stack.h index a12618c1..b0e5d351 100644 --- a/include/etl/stack.h +++ b/include/etl/stack.h @@ -47,8 +47,6 @@ SOFTWARE. #include "error_handler.h" #include "debug_count.h" #include "type_traits.h" -#include "parameter_type.h" -#include "type_traits.h" #undef ETL_FILE #define ETL_FILE "15" @@ -231,13 +229,15 @@ namespace etl typedef T value_type; ///< The type stored in the stack. typedef T& reference; ///< A reference to the type used in the stack. typedef const T& const_reference; ///< A const reference to the type used in the stack. +#if ETL_CPP11_SUPPORTED + typedef T&& rvalue_reference;///< An rvalue reference to the type used in the stack. +#endif typedef T* pointer; ///< A pointer to the type used in the stack. typedef const T* const_pointer; ///< A const pointer to the type used in the stack. typedef stack_base::size_type size_type; ///< The type used for determining the size of the stack. private: - typedef typename etl::parameter_type::type parameter_t; typedef typename etl::stack_base base_t; public: @@ -256,7 +256,7 @@ namespace etl /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. ///\param value The value to push to the stack. //************************************************************************* - void push(parameter_t value) + void push(const_reference value) { #if defined(ETL_CHECK_PUSH_POP) ETL_ASSERT(!full(), ETL_ERROR(stack_full)); @@ -265,6 +265,22 @@ namespace etl ::new (&p_buffer[top_index]) T(value); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Adds a value to the stack. + /// If asserts or exceptions are enabled, throws an etl::stack_full if the stack is already full. + ///\param value The value to push to the stack. + //************************************************************************* + void push(rvalue_reference value) + { +#if defined(ETL_CHECK_PUSH_POP) + ETL_ASSERT(!full(), ETL_ERROR(stack_full)); +#endif + base_t::add_in(); + ::new (&p_buffer[top_index]) T(etl::move(value)); + } +#endif + #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) //************************************************************************* /// Constructs a value in the stack place'. @@ -425,6 +441,22 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Assignment operator. + //************************************************************************* + istack& operator = (istack&& rhs) + { + if (&rhs != this) + { + clear(); + clone(etl::move(rhs)); + } + + return *this; + } +#endif + protected: //************************************************************************* @@ -440,6 +472,21 @@ namespace etl } } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Make this a clone of the supplied stack + //************************************************************************* + void clone(istack&& other) + { + size_t index = 0; + + for (size_t i = 0; i < other.size(); ++i) + { + push(etl::move(other.p_buffer[index++])); + } + } +#endif + //************************************************************************* /// The constructor that is called from derived classes. //************************************************************************* @@ -503,6 +550,17 @@ namespace etl etl::istack::clone(rhs); } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Copy constructor + //************************************************************************* + stack(stack&& rhs) + : etl::istack(reinterpret_cast(&buffer[0]), SIZE) + { + etl::istack::clone(etl::move(rhs)); + } +#endif + //************************************************************************* /// Destructor. //************************************************************************* @@ -524,6 +582,21 @@ namespace etl return *this; } +#if ETL_CPP11_SUPPORTED + //************************************************************************* + /// Move assignment operator. + //************************************************************************* + stack& operator = (stack&& rhs) + { + if (&rhs != this) + { + etl::istack::clone(etl::move(rhs)); + } + + return *this; + } +#endif + private: /// The unintitialised buffer of T used in the stack. diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index f1fdbc58..0fbf950a 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -1319,13 +1319,13 @@ namespace etl /// Template to determine if a type is one of a specified list. ///\ingroup types template struct is_one_of { - static const bool value = + static const bool value = etlstd::is_same::value || etlstd::is_same::value || etlstd::is_same::value || @@ -1370,6 +1370,10 @@ namespace etl typedef type_t* pointer; typedef const type_t* const_pointer; typedef const type_t* const const_pointer_const; + +#if ETL_CPP11_SUPPORTED + typedef type_t&& rvalue_reference; +#endif }; // Pointers. @@ -1388,6 +1392,10 @@ namespace etl typedef type_t* pointer; typedef const type_t* const_pointer; typedef const type_t* const const_pointer_const; + +#if ETL_CPP11_SUPPORTED + typedef type_t&& rvalue_reference; +#endif }; // Pointers. @@ -1406,6 +1414,10 @@ namespace etl typedef type_t* pointer; typedef const type_t* const_pointer; typedef const type_t* const const_pointer_const; + +#if ETL_CPP11_SUPPORTED + typedef type_t&& rvalue_reference; +#endif }; // References. @@ -1424,6 +1436,10 @@ namespace etl typedef type_t* pointer; typedef const type_t* const_pointer; typedef const type_t* const const_pointer_const; + +#if ETL_CPP11_SUPPORTED + typedef type_t&& rvalue_reference; +#endif }; #if ETL_CPP11_SUPPORTED @@ -1443,6 +1459,10 @@ namespace etl typedef type_t* pointer; typedef const type_t* const_pointer; typedef const type_t* const const_pointer_const; + +#if ETL_CPP11_SUPPORTED + typedef type_t&& rvalue_reference; +#endif }; #endif @@ -1456,6 +1476,9 @@ namespace etl template using types_cr = typename types::const_reference; + template + using types_rr = typename types::rvalue_reference; + template using types_p = typename types::pointer; diff --git a/include/etl/type_traits_generator.h b/include/etl/type_traits_generator.h index e1ebc66b..f2ea2da3 100644 --- a/include/etl/type_traits_generator.h +++ b/include/etl/type_traits_generator.h @@ -1463,6 +1463,9 @@ namespace etl template using types_cr = typename types::const_reference; + template + using types_rr = typename types::rvalue_reference; + template using types_p = typename types::pointer; diff --git a/include/etl/utility.h b/include/etl/utility.h index b08ac571..a5f1af4e 100644 --- a/include/etl/utility.h +++ b/include/etl/utility.h @@ -43,6 +43,28 @@ SOFTWARE. namespace etl { +#if ETL_CPP11_SUPPORTED + //****************************************************************************** + template + constexpr typename etl::remove_reference::type&& move(T&& t) noexcept + { + return static_cast::type&&>(t); + } + + //****************************************************************************** + template + constexpr T&& forward(typename etl::remove_reference::type& t) noexcept + { + return static_cast(t); + } + + template + constexpr T&& forward(typename etl::remove_reference::type&& t) noexcept + { + return static_cast(t); + } +#endif + //****************************************************************************** template struct pair @@ -53,48 +75,114 @@ namespace etl T1 first; T2 second; - pair() - : first(T1()), - second(T2()) + /// Default constructor + ETL_CONSTEXPR pair() + : first(T1()) + , second(T2()) { } - pair(const T1& a, const T2& b) - : first(a), - second(b) + /// Constructor from parameters + ETL_CONSTEXPR14 pair(const T1& a, const T2& b) + : first(a) + , second(b) { } +#if ETL_CPP11_SUPPORTED + /// Move constructor from parameters template - pair(const pair& other) - : first(other.first), - second(other.second) + ETL_CONSTEXPR14 pair(U1&& a, U2&& b) + : first(etl::forward(a)) + , second(etl::forward(b)) + { + } +#endif + + /// Copy constructor + template + ETL_CONSTEXPR14 pair(const pair& other) + : first(other.first) + , second(other.second) { } + /// Copy constructor pair(const pair& other) - : first(other.first), - second(other.second) + : first(other.first) + , second(other.second) { } +#if ETL_CPP11_SUPPORTED + /// Move constructor + template + ETL_CONSTEXPR14 pair(pair&& other) + : first(etl::move(other.first)) + , second(etl::move(other.second)) + { + } +#endif + void swap(pair& other) { - T1 temp1 = first; - T2 temp2 = second; - first = other.first; - second = other.second; - other.first = temp1; - other.second = temp2; + using ETL_OR_STD::swap; + + swap(first, other.first); + swap(second, other.second); } + + pair& operator =(const pair& other) + { + first = other.first; + second = other.second; + + return *this; + } + + template + pair& operator =(const pair& other) + { + first = other.first; + second = other.second; + + return *this; + } + +#if ETL_CPP11_SUPPORTED + pair& operator =(pair&& other) + { + first = etl::move(other.first); + second = etl::move(other.second); + + return *this; + } + + template + pair& operator =(pair&& other) + { + first = etl::move(other.first); + second = etl::move(other.second); + + return *this; + } +#endif }; //****************************************************************************** +#if ETL_CPP11_SUPPORTED + template + inline pair make_pair(T1&& a, T2&& b) + { + return pair(etl::move(a), etl::move(b)); + } +#else template inline pair make_pair(T1 a, T2 b) { return pair(a, b); } +#endif //****************************************************************************** template @@ -141,28 +229,6 @@ namespace etl return !(a < b); } -#if ETL_CPP11_SUPPORTED - //****************************************************************************** - template - constexpr typename etl::remove_reference::type&& move(T&& t) noexcept - { - return static_cast::type&&>(t); - } - - //****************************************************************************** - template - constexpr T&& forward(typename etl::remove_reference::type& t) noexcept - { - return static_cast(t); - } - - template - constexpr T&& forward(typename etl::remove_reference::type&& t) noexcept - { - return static_cast(t); - } -#endif - #if defined(ETL_NO_STL) || !ETL_CPP14_SUPPORTED //*************************************************************************** /// exchange (const) diff --git a/include/etl/vector.h b/include/etl/vector.h index 03305767..cb7abb85 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -541,7 +541,7 @@ namespace etl else { create_back(back()); - etl::copy_backward(position, p_end - 2, p_end - 1); + etl::move_backward(position, p_end - 2, p_end - 1); *position = value; } @@ -594,7 +594,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - etl::copy_backward(position, p_end - 2, p_end - 1); + etl::move_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -619,7 +619,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - etl::copy_backward(position, p_end - 2, p_end - 1); + etl::move_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -644,7 +644,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - etl::copy_backward(position, p_end - 2, p_end - 1); + etl::move_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -669,7 +669,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - etl::copy_backward(position, p_end - 2, p_end - 1); + etl::move_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -694,7 +694,7 @@ namespace etl { p = etl::addressof(*position); create_back(back()); - etl::copy_backward(position, p_end - 2, p_end - 1); + etl::move_backward(position, p_end - 2, p_end - 1); (*position).~T(); } @@ -741,11 +741,11 @@ namespace etl size_t construct_new_n = insert_n - copy_new_n; // Construct old. - etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old); + etl::uninitialized_move(p_end - construct_old_n, p_end, p_construct_old); ETL_ADD_DEBUG_COUNT(construct_old_n) // Copy old. - etl::copy_backward(p_buffer + insert_begin, p_buffer + insert_begin + copy_old_n, p_buffer + insert_end + copy_old_n); + etl::move_backward(p_buffer + insert_begin, p_buffer + insert_begin + copy_old_n, p_buffer + insert_end + copy_old_n); // Construct new. etl::uninitialized_fill_n(p_end, construct_new_n, value); @@ -776,7 +776,7 @@ namespace etl size_t insert_begin = etl::distance(begin(), position); size_t insert_end = insert_begin + insert_n; - // Copy old data. + // Move old data. size_t copy_old_n; size_t construct_old_n; iterator p_construct_old; @@ -797,19 +797,19 @@ namespace etl size_t copy_new_n = construct_old_n; size_t construct_new_n = insert_n - copy_new_n; - // Construct old. - etl::uninitialized_copy_n(p_end - construct_old_n, construct_old_n, p_construct_old); + // Move construct old. + etl::uninitialized_move(p_end - construct_old_n, p_end, p_construct_old); ETL_ADD_DEBUG_COUNT(construct_old_n) - // Copy old. - etl::copy_backward(p_buffer + insert_begin, p_buffer + insert_begin + copy_old_n, p_buffer + insert_end + copy_old_n); + // Move old. + etl::move_backward(p_buffer + insert_begin, p_buffer + insert_begin + copy_old_n, p_buffer + insert_end + copy_old_n); - // Construct new. - etl::uninitialized_copy_n(first + copy_new_n, construct_new_n, p_end); + // Copy construct new. + etl::uninitialized_copy(first + copy_new_n, first + copy_new_n + construct_new_n, p_end); ETL_ADD_DEBUG_COUNT(construct_new_n) // Copy new. - etl::copy_n(first, copy_new_n, p_buffer + insert_begin); + etl::copy(first, first + copy_new_n, p_buffer + insert_begin); p_end += count; } @@ -821,7 +821,7 @@ namespace etl //********************************************************************* iterator erase(iterator i_element) { - etl::copy(i_element + 1, end(), i_element); + etl::move(i_element + 1, end(), i_element); destroy_back(); return i_element; @@ -843,7 +843,7 @@ namespace etl } else { - etl::copy(last, end(), first); + etl::move(last, end(), first); size_t n_delete = etl::distance(first, last); // Destroy the elements left over at the end. diff --git a/include/etl/version.h b/include/etl/version.h index 93b5e668..9d687c0c 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -38,9 +38,8 @@ SOFTWARE. ///\ingroup utilities #define ETL_VERSION_MAJOR 16 -#define ETL_VERSION_MINOR 3 -#define ETL_VERSION_PATCH 1 - +#define ETL_VERSION_MINOR 4 +#define ETL_VERSION_PATCH 0 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index eae020a0..83d58cc0 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "16.3.1", + "version": "16.4.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 8dea8fd3..9837f2dd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=16.3.1 +version=16.4.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 4cc6ae34..28f60f6a 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,6 +1,7 @@ =============================================================================== -16.3.1 -Removed incorrect ETL_ALWAYS_ASSERT from etl::callback_timer +16.4.0 +Added rvalue references and 'move' API to all containers, except etl::priority_queue +and etl::variant =============================================================================== 16.3.0 diff --git a/test/data.h b/test/data.h index 271c7fa3..a1756736 100644 --- a/test/data.h +++ b/test/data.h @@ -204,6 +204,8 @@ public: other.value = T(); other.valid = false; + + return *this; } bool operator < (const TestDataM& other) const diff --git a/test/test_array.cpp b/test/test_array.cpp index 6d5600e6..89bc39b7 100644 --- a/test/test_array.cpp +++ b/test/test_array.cpp @@ -375,12 +375,6 @@ namespace data.assign(&source[0], &source[5], 99); isEqual = std::equal(data.begin(), data.end(), std::begin(check2)); CHECK(isEqual); - - // Assign larger. - data.assign(std::begin(initial), std::end(initial)); - data.assign(&source[0], &source[13]); - isEqual = std::equal(data.begin(), data.end(), std::begin(check3)); - CHECK(isEqual); } //************************************************************************* diff --git a/test/test_deque.cpp b/test/test_deque.cpp index f9532ebf..e322ac75 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -180,12 +180,55 @@ namespace CHECK_EQUAL(0U, deque1.size()); CHECK_EQUAL(4U, deque2.size()); - CHECK_EQUAL(1U, *deque2[0]); + std::unique_ptr pr = std::move(*deque2.begin()); + + CHECK_EQUAL(1U, *pr); CHECK_EQUAL(2U, *deque2[1]); CHECK_EQUAL(3U, *deque2[2]); CHECK_EQUAL(4U, *deque2[3]); } + //************************************************************************* + TEST(test_move_insert_erase) + { + const size_t SIZE = 10U; + typedef etl::deque, SIZE> Data; + + std::unique_ptr p1(new uint32_t(1U)); + std::unique_ptr p2(new uint32_t(2U)); + std::unique_ptr p3(new uint32_t(3U)); + std::unique_ptr p4(new uint32_t(4U)); + + Data deque1; + deque1.push_back(std::move(p1)); + deque1.push_back(std::move(p2)); + deque1.push_back(std::move(p4)); + + deque1.insert(deque1.begin() + 2U, std::move(p3)); + + CHECK_EQUAL(4U, deque1.size()); + + CHECK(bool(deque1[0])); + CHECK(bool(deque1[1])); + CHECK(bool(deque1[2])); + CHECK(bool(deque1[3])); + + CHECK_EQUAL(1U, *deque1[0]); + CHECK_EQUAL(2U, *deque1[1]); + CHECK_EQUAL(3U, *deque1[2]); + CHECK_EQUAL(4U, *deque1[3]); + + deque1.erase(deque1.begin() + 1); + + CHECK(bool(deque1[0])); + CHECK(bool(deque1[1])); + CHECK(bool(deque1[2])); + + CHECK_EQUAL(1U, *deque1[0]); + CHECK_EQUAL(3U, *deque1[1]); + CHECK_EQUAL(4U, *deque1[2]); + } + //************************************************************************* TEST(test_assignment) { diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index f6f50804..1029f6df 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -48,6 +48,7 @@ namespace typedef TestDataDC DC; typedef TestDataNDC NDC; + typedef TestDataM MC; typedef ETL_OR_STD::pair ElementDC; typedef ETL_OR_STD::pair ElementNDC; @@ -61,6 +62,9 @@ namespace typedef etl::flat_map DataInt; + typedef etl::flat_map DataM; + typedef etl::iflat_map IDataM; + typedef std::map Compare_DataDC; typedef std::map Compare_DataNDC; @@ -354,6 +358,40 @@ namespace } #endif + //************************************************************************* + TEST(test_move_constructor) + { + using Item = ETL_OR_STD::pair; + + Item p1(1, MC("1")); + Item p2(2, "2"); + Item p3(3, "3"); + Item p4(4, MC("4")); + + DataM data1; + data1.insert(std::move(p1)); + data1.insert(std::move(p2)); + data1.insert(std::move(p3)); + data1.insert(std::move(p4)); + + CHECK(!bool(p1.second)); + CHECK(!bool(p2.second)); + CHECK(!bool(p3.second)); + CHECK(!bool(p4.second)); + + DataM data2(std::move(data1)); + + CHECK_EQUAL(4U, data1.size()); // Move does not clear the source. + CHECK_EQUAL(4U, data2.size()); + + DataM::const_iterator itr = data2.begin(); + + CHECK_EQUAL("1", (*itr++).second.value); + CHECK_EQUAL("2", (*itr++).second.value); + CHECK_EQUAL("3", (*itr++).second.value); + CHECK_EQUAL("4", (*itr++).second.value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index 8b4697bc..0513e0c9 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -46,6 +46,7 @@ namespace typedef TestDataDC DC; typedef TestDataNDC NDC; + typedef TestDataM MC; typedef ETL_OR_STD::pair ElementDC; typedef ETL_OR_STD::pair ElementNDC; @@ -59,6 +60,9 @@ namespace typedef etl::flat_multimap DataInt; + typedef etl::flat_multimap DataM; + typedef etl::iflat_multimap IDataM; + typedef std::multimap Compare_DataDC; typedef std::multimap Compare_DataNDC; @@ -337,6 +341,44 @@ namespace } #endif + //************************************************************************* + TEST(test_move_constructor) + { + using Item = ETL_OR_STD::pair; + + Item p1(1, MC("1")); + Item p2a(2, "2a"); + Item p2b(2, "2b"); + Item p3(3, "3"); + Item p4(4, MC("4")); + + DataM data1; + data1.insert(std::move(p1)); + data1.insert(std::move(p2a)); + data1.insert(std::move(p3)); + data1.insert(std::move(p4)); + data1.insert(std::move(p2b)); + + CHECK(!bool(p1.second)); + CHECK(!bool(p2a.second)); + CHECK(!bool(p2b.second)); + CHECK(!bool(p3.second)); + CHECK(!bool(p4.second)); + + DataM data2(std::move(data1)); + + CHECK_EQUAL(5U, data1.size()); // Move does not clear the source. + CHECK_EQUAL(5U, data2.size()); + + DataM::const_iterator itr = data2.begin(); + + CHECK_EQUAL("1", (*itr++).second.value); + CHECK_EQUAL("2a", (*itr++).second.value); + CHECK_EQUAL("2b", (*itr++).second.value); + CHECK_EQUAL("3", (*itr++).second.value); + CHECK_EQUAL("4", (*itr++).second.value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index d323ccbf..ab89f887 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -46,6 +46,7 @@ namespace typedef TestDataDC DC; typedef TestDataNDC NDC; + typedef TestDataM MC; typedef etl::flat_multiset DataDC; typedef etl::flat_multiset DataNDC; @@ -53,6 +54,9 @@ namespace typedef etl::flat_multiset DataInt; + typedef etl::flat_multiset DataM; + typedef etl::iflat_multiset IDataM; + typedef std::multiset Compare_DataDC; typedef std::multiset Compare_DataNDC; @@ -300,6 +304,46 @@ namespace } #endif + //************************************************************************* + TEST(test_move_constructor) + { + using Item = MC; + + Item p1(Item("1")); + Item p2a("2a"); + Item p2b("2b"); + Item p3("3"); + Item p4(Item("4")); + + DataM data1; + data1.insert(std::move(p1)); + data1.insert(std::move(p2a)); + data1.insert(std::move(p3)); + data1.insert(std::move(p4)); + data1.insert(std::move(p2b)); + + CHECK(!bool(p1)); + CHECK(!bool(p2a)); + CHECK(!bool(p2b)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + DataM data2(std::move(data1)); + + CHECK_EQUAL(5U, data1.size()); // Move does not clear the source. + CHECK_EQUAL(5U, data2.size()); + + DataM::iterator itr = data2.begin(); + + Item pr = std::move(*itr++); + + CHECK_EQUAL("1", pr.value); + CHECK_EQUAL("2a", (*itr++).value); + CHECK_EQUAL("2b", (*itr++).value); + CHECK_EQUAL("3", (*itr++).value); + CHECK_EQUAL("4", (*itr++).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 11d94dd7..2e47f4da 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -46,6 +46,7 @@ namespace typedef TestDataDC DC; typedef TestDataNDC NDC; + typedef TestDataM MC; typedef etl::flat_set DataDC; typedef etl::flat_set DataNDC; @@ -53,6 +54,9 @@ namespace typedef etl::flat_set DataInt; + typedef etl::flat_set DataM; + typedef etl::iflat_set IDataM; + typedef std::set Compare_DataDC; typedef std::set Compare_DataNDC; @@ -312,6 +316,42 @@ namespace } #endif + //************************************************************************* + TEST(test_move_constructor) + { + using Item = MC; + + Item p1("1"); + Item p2("2"); + Item p3("3"); + Item p4("4"); + + DataM data1; + data1.insert(std::move(p1)); + data1.insert(std::move(p2)); + data1.insert(std::move(p3)); + data1.insert(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + DataM data2(std::move(data1)); + + CHECK_EQUAL(4U, data1.size()); // Move does not clear the source. + CHECK_EQUAL(4U, data2.size()); + + DataM::iterator itr = data2.begin(); + + Item pr = std::move(*itr++); + + CHECK_EQUAL("1", pr.value); + CHECK_EQUAL("2", (*itr++).value); + CHECK_EQUAL("3", (*itr++).value); + CHECK_EQUAL("4", (*itr++).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_list.cpp b/test/test_list.cpp index ae292f13..79c4c876 100644 --- a/test/test_list.cpp +++ b/test/test_list.cpp @@ -230,9 +230,11 @@ namespace CHECK_EQUAL(0U, data1.size()); CHECK_EQUAL(4U, data2.size()); - DataM::const_iterator itr = data2.begin(); + DataM::iterator itr = data2.begin(); - CHECK_EQUAL(1U, (*itr++).value); + ItemM pr = std::move(*itr++); + + CHECK_EQUAL(1U, pr.value); CHECK_EQUAL(2U, (*itr++).value); CHECK_EQUAL(3U, (*itr++).value); CHECK_EQUAL(4U, (*itr++).value); diff --git a/test/test_map.cpp b/test/test_map.cpp index aa6dc61a..384fc8ba 100755 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -38,23 +38,28 @@ SOFTWARE. #include "etl/map.h" +#include "data.h" + static const size_t MAX_SIZE = 10; #define TEST_GREATER_THAN #ifdef TEST_GREATER_THAN -typedef etl::map > Data; -typedef etl::imap > IData; -typedef std::map > Compare_Data; +using Data = etl::map>; +using IData = etl::imap>; +using Compare_Data = std::map>; #else -typedef etl::map > Data; -typedef etl::imap > IData; -typedef std::map > Compare_Data; +using Data = etl::map>; +using IData = etl::imap>; +using Compare_Data = std::map>; #endif -typedef Data::iterator Data_iterator; -typedef Data::const_iterator Data_const_iterator; -typedef Compare_Data::iterator Compare_Data_iterator; -typedef Compare_Data::const_iterator Compare_Data_const_iterator; +using ItemM = TestDataM; +using DataM = etl::map; + +using Data_iterator = Data::iterator; +using Data_const_iterator = Data::const_iterator; +using Compare_Data_iterator = Compare_Data::iterator; +using Compare_Data_const_iterator = Compare_Data::const_iterator; //************************************************************************* static std::ostream& operator << (std::ostream& os, const Data_iterator& it) @@ -220,6 +225,53 @@ namespace CHECK(data.begin() == data.end()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data1(compare_data.begin(), compare_data.end()); + Data data2(data1); + + CHECK_EQUAL(initial_data.size(), data1.size()); + CHECK(data1.size() == data2.size()); + + bool isEqual = false; + + isEqual = Check_Equal(data1.begin(), + data1.end(), + compare_data.begin()); + CHECK(isEqual); + + isEqual = Check_Equal(data2.begin(), + data2.end(), + compare_data.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + DataM data1; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data1.insert(DataM::value_type(std::string("1"), etl::move(d1))); + data1.insert(DataM::value_type(std::string("2"), etl::move(d2))); + data1.insert(DataM::value_type(std::string("3"), etl::move(d3))); + data1.insert(DataM::value_type(std::string("4"), ItemM(4))); + + DataM data2(std::move(data1)); + + CHECK(!data1.empty()); // Move does not clear the source. + + CHECK_EQUAL(1, data2.at("1").value); + CHECK_EQUAL(2, data2.at("2").value); + CHECK_EQUAL(3, data2.at("3").value); + CHECK_EQUAL(4, data2.at("4").value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_destruct_via_imap) { @@ -312,6 +364,29 @@ namespace CHECK(isEqual); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + DataM data1; + DataM data2; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data1.insert(DataM::value_type(std::string("1"), etl::move(d1))); + data1.insert(DataM::value_type(std::string("2"), etl::move(d2))); + data1.insert(DataM::value_type(std::string("3"), etl::move(d3))); + data1.insert(DataM::value_type(std::string("4"), ItemM(4))); + + data2 = std::move(data1); + + CHECK_EQUAL(1, data2.at("1").value); + CHECK_EQUAL(2, data2.at("2").value); + CHECK_EQUAL(3, data2.at("3").value); + CHECK_EQUAL(4, data2.at("4").value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { @@ -523,6 +598,30 @@ namespace CHECK(isEqual); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_insert_moved_value) + { + DataM data; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data.insert(DataM::value_type(std::string("1"), etl::move(d1))); + data.insert(DataM::value_type(std::string("2"), etl::move(d2))); + data.insert(DataM::value_type(std::string("3"), etl::move(d3))); + data.insert(DataM::value_type(std::string("4"), ItemM(4))); + + CHECK(!bool(d1)); + CHECK(!bool(d2)); + CHECK(!bool(d3)); + + CHECK_EQUAL(1, data.at("1").value); + CHECK_EQUAL(2, data.at("2").value); + CHECK_EQUAL(3, data.at("3").value); + CHECK_EQUAL(4, data.at("4").value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_insert_value_changed) { diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 796f2b63..2b156022 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -31,6 +31,8 @@ SOFTWARE. #include "etl/memory.h" #include "etl/debug_count.h" +#include "data.h" + #include #include #include @@ -43,6 +45,7 @@ namespace { typedef std::string non_trivial_t; typedef uint32_t trivial_t; + typedef TestDataM moveable_t; const size_t SIZE = 10; @@ -64,9 +67,11 @@ namespace char buffer_non_trivial[sizeof(non_trivial_t) * SIZE]; char buffer_trivial[sizeof(trivial_t) * SIZE]; + char buffer_moveable[sizeof(moveable_t) * SIZE]; non_trivial_t* output_non_trivial = reinterpret_cast(buffer_non_trivial); - trivial_t* output_trivial = reinterpret_cast(buffer_trivial); + trivial_t* output_trivial = reinterpret_cast(buffer_trivial); + moveable_t* output_moveable = reinterpret_cast(buffer_moveable); struct overloaded { @@ -318,6 +323,136 @@ namespace CHECK_EQUAL(0U, count); } + //************************************************************************* + TEST(test_uninitialized_move) + { + bool is_equal; + + // Non count. + moveable_t* p = reinterpret_cast(buffer_moveable); + + std::fill(std::begin(buffer_moveable), std::end(buffer_moveable), 0); + + { + std::array test_data_moveable = + { + moveable_t(0), moveable_t(1), moveable_t(2), moveable_t(3), moveable_t(4), + moveable_t(5), moveable_t(6), moveable_t(7), moveable_t(8), moveable_t(9) + }; + + etl::uninitialized_move(test_data_moveable.begin(), test_data_moveable.end(), p); + } + + is_equal = (output_moveable[0] == moveable_t(0)) && + (output_moveable[1] == moveable_t(1)) && + (output_moveable[2] == moveable_t(2)) && + (output_moveable[3] == moveable_t(3)) && + (output_moveable[4] == moveable_t(4)) && + (output_moveable[5] == moveable_t(5)) && + (output_moveable[6] == moveable_t(6)) && + (output_moveable[7] == moveable_t(7)) && + (output_moveable[8] == moveable_t(8)) && + (output_moveable[9] == moveable_t(9)); + + CHECK(is_equal); + etl::destroy(p, p + SIZE); + + // Count. + size_t count = 0; + std::fill(std::begin(buffer_non_trivial), std::end(buffer_non_trivial), 0); + + { + std::array test_data_moveable = + { + moveable_t(0), moveable_t(1), moveable_t(2), moveable_t(3), moveable_t(4), + moveable_t(5), moveable_t(6), moveable_t(7), moveable_t(8), moveable_t(9) + }; + + etl::uninitialized_move(test_data_moveable.begin(), test_data_moveable.end(), p, count); + } + + is_equal = (output_moveable[0] == moveable_t(0)) && + (output_moveable[1] == moveable_t(1)) && + (output_moveable[2] == moveable_t(2)) && + (output_moveable[3] == moveable_t(3)) && + (output_moveable[4] == moveable_t(4)) && + (output_moveable[5] == moveable_t(5)) && + (output_moveable[6] == moveable_t(6)) && + (output_moveable[7] == moveable_t(7)) && + (output_moveable[8] == moveable_t(8)) && + (output_moveable[9] == moveable_t(9)); + + CHECK(is_equal); + CHECK_EQUAL(SIZE, count); + etl::destroy(p, p + SIZE, count); + CHECK_EQUAL(0U, count); + } + + //************************************************************************* + TEST(test_uninitialized_move_n) + { + bool is_equal; + + // Non count. + moveable_t* p = reinterpret_cast(buffer_moveable); + + std::fill(std::begin(buffer_moveable), std::end(buffer_moveable), 0); + + { + std::array test_data_moveable = + { + moveable_t(0), moveable_t(1), moveable_t(2), moveable_t(3), moveable_t(4), + moveable_t(5), moveable_t(6), moveable_t(7), moveable_t(8), moveable_t(9) + }; + + etl::uninitialized_move_n(test_data_moveable.begin(), SIZE, p); + } + + is_equal = (output_moveable[0] == moveable_t(0)) && + (output_moveable[1] == moveable_t(1)) && + (output_moveable[2] == moveable_t(2)) && + (output_moveable[3] == moveable_t(3)) && + (output_moveable[4] == moveable_t(4)) && + (output_moveable[5] == moveable_t(5)) && + (output_moveable[6] == moveable_t(6)) && + (output_moveable[7] == moveable_t(7)) && + (output_moveable[8] == moveable_t(8)) && + (output_moveable[9] == moveable_t(9)); + + CHECK(is_equal); + etl::destroy(p, p + SIZE); + + // Count. + size_t count = 0; + std::fill(std::begin(buffer_non_trivial), std::end(buffer_non_trivial), 0); + + { + std::array test_data_moveable = + { + moveable_t(0), moveable_t(1), moveable_t(2), moveable_t(3), moveable_t(4), + moveable_t(5), moveable_t(6), moveable_t(7), moveable_t(8), moveable_t(9) + }; + + etl::uninitialized_move_n(test_data_moveable.begin(), SIZE, p, count); + } + + is_equal = (output_moveable[0] == moveable_t(0)) && + (output_moveable[1] == moveable_t(1)) && + (output_moveable[2] == moveable_t(2)) && + (output_moveable[3] == moveable_t(3)) && + (output_moveable[4] == moveable_t(4)) && + (output_moveable[5] == moveable_t(5)) && + (output_moveable[6] == moveable_t(6)) && + (output_moveable[7] == moveable_t(7)) && + (output_moveable[8] == moveable_t(8)) && + (output_moveable[9] == moveable_t(9)); + + CHECK(is_equal); + CHECK_EQUAL(SIZE, count); + etl::destroy(p, p + SIZE, count); + CHECK_EQUAL(0U, count); + } + //************************************************************************* TEST(test_uninitialized_default_construct_n_trivial) { diff --git a/test/test_multimap.cpp b/test/test_multimap.cpp index f2633ed6..5440fcc8 100755 --- a/test/test_multimap.cpp +++ b/test/test_multimap.cpp @@ -38,23 +38,28 @@ SOFTWARE. #include "etl/multimap.h" +#include "data.h" + static const size_t MAX_SIZE = 10; #define TEST_GREATER_THAN #ifdef TEST_GREATER_THAN -typedef etl::multimap > Data; -typedef etl::imultimap > IData; -typedef std::multimap > Compare_Data; +using Data = etl::multimap>; +using IData = etl::imultimap>; +using Compare_Data = std::multimap>; #else -typedef etl::multimap > Data; -typedef etl::imultimap > IData; -typedef std::multimap > Compare_Data; +using Data = etl::multimap>; +using IData = etl::imultimap>; +using Compare_Data = std::multimap>; #endif -typedef Data::iterator Data_iterator; -typedef Data::const_iterator Data_const_iterator; -typedef Compare_Data::iterator Compare_Data_iterator; -typedef Compare_Data::const_iterator Compare_Data_const_iterator; +using ItemM = TestDataM; +using DataM = etl::multimap; + +using Data_iterator = Data::iterator; +using Data_const_iterator = Data::const_iterator; +using Compare_Data_iterator = Compare_Data::iterator; +using Compare_Data_const_iterator = Compare_Data::const_iterator; //************************************************************************* static std::ostream& operator << (std::ostream& os, const Data_iterator& it) @@ -222,6 +227,53 @@ namespace CHECK(data.begin() == data.end()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data1(compare_data.begin(), compare_data.end()); + Data data2(data1); + + CHECK_EQUAL(initial_data.size(), data1.size()); + CHECK(data1.size() == data2.size()); + + bool isEqual = false; + + isEqual = Check_Equal(data1.begin(), + data1.end(), + compare_data.begin()); + CHECK(isEqual); + + isEqual = Check_Equal(data2.begin(), + data2.end(), + compare_data.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + DataM data1; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data1.insert(DataM::value_type(std::string("1"), etl::move(d1))); + data1.insert(DataM::value_type(std::string("2"), etl::move(d2))); + data1.insert(DataM::value_type(std::string("3"), etl::move(d3))); + data1.insert(DataM::value_type(std::string("4"), ItemM(4))); + + DataM data2(std::move(data1)); + + CHECK(!data1.empty()); // Move does not clear the source. + + CHECK_EQUAL(1, data2.find("1")->second.value); + CHECK_EQUAL(2, data2.find("2")->second.value); + CHECK_EQUAL(3, data2.find("3")->second.value); + CHECK_EQUAL(4, data2.find("4")->second.value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_destruct_via_imultimap) { @@ -311,6 +363,29 @@ namespace CHECK(isEqual); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + DataM data1; + DataM data2; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data1.insert(DataM::value_type(std::string("1"), etl::move(d1))); + data1.insert(DataM::value_type(std::string("2"), etl::move(d2))); + data1.insert(DataM::value_type(std::string("3"), etl::move(d3))); + data1.insert(DataM::value_type(std::string("4"), ItemM(4))); + + data2 = std::move(data1); + + CHECK_EQUAL(1, data2.find("1")->second.value); + CHECK_EQUAL(2, data2.find("2")->second.value); + CHECK_EQUAL(3, data2.find("3")->second.value); + CHECK_EQUAL(4, data2.find("4")->second.value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_multiset.cpp b/test/test_multiset.cpp index 146f76a2..f0773683 100755 --- a/test/test_multiset.cpp +++ b/test/test_multiset.cpp @@ -38,23 +38,28 @@ SOFTWARE. #include "etl/multiset.h" +#include "data.h" + static const size_t MAX_SIZE = 10; #define TEST_GREATER_THAN #ifdef TEST_GREATER_THAN -typedef etl::multiset > Data; -typedef etl::imultiset > IData; -typedef std::multiset > Compare_Data; +using Data = etl::multiset>; +using IData = etl::imultiset>; +using Compare_Data = std::multiset>; #else -typedef etl::multiset > Data; -typedef etl::multiset > IData; -typedef std::multiset > Compare_Data; +using Data = etl::multiset>; +using IData = etl::multiset>; +using Compare_Data = std::multiset>; #endif -typedef Data::iterator Data_iterator; -typedef Data::const_iterator Data_const_iterator; -typedef Compare_Data::iterator Compare_Data_iterator; -typedef Compare_Data::const_iterator Compare_Data_const_iterator; +using ItemM = TestDataM; +using DataM = etl::multiset; + +using Data_iterator = Data::iterator; +using Data_const_iterator = Data::const_iterator; +using Compare_Data_iterator = Compare_Data::iterator; +using Compare_Data_const_iterator = Compare_Data::const_iterator; //************************************************************************* static std::ostream& operator << (std::ostream& os, const Data_iterator& it) @@ -214,6 +219,53 @@ namespace CHECK(data.begin() == data.end()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data1(compare_data.begin(), compare_data.end()); + Data data2(data1); + + CHECK_EQUAL(initial_data.size(), data1.size()); + CHECK(data1.size() == data2.size()); + + bool isEqual = false; + + isEqual = Check_Equal(data1.begin(), + data1.end(), + compare_data.begin()); + CHECK(isEqual); + + isEqual = Check_Equal(data2.begin(), + data2.end(), + compare_data.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + //DataM data1; + + //ItemM d1(1); + //ItemM d2(2); + //ItemM d3(3); + + //data1.insert(etl::move(d1)); + //data1.insert(etl::move(d2)); + //data1.insert(etl::move(d3)); + //data1.insert(ItemM(4)); + + //DataM data2(std::move(data1)); + + //CHECK(data1.empty()); + + //CHECK_EQUAL(1, ItemM(1).value); + //CHECK_EQUAL(2, ItemM(2).value); + //CHECK_EQUAL(3, ItemM(3).value); + //CHECK_EQUAL(4, ItemM(4).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_destruct_via_imultiset) { @@ -298,6 +350,32 @@ namespace CHECK(isEqual); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + //DataM data1; + + //ItemM d1(1); + //ItemM d2(2); + //ItemM d3(3); + + //data1.insert(etl::move(d1)); + //data1.insert(etl::move(d2)); + //data1.insert(etl::move(d3)); + //data1.insert(ItemM(4)); + + //DataM data2; + + //data2 = std::move(data1); + + //CHECK(data1.empty()); + + //CHECK_EQUAL(1, ItemM(1).value); + //CHECK_EQUAL(2, ItemM(2).value); + //CHECK_EQUAL(3, ItemM(3).value); + //CHECK_EQUAL(4, ItemM(4).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_optional.cpp b/test/test_optional.cpp index 1851d3af..77b0b687 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -31,6 +31,9 @@ SOFTWARE. #include #include +#include + + #include "etl/optional.h" #include "etl/vector.h" #include "data.h" @@ -103,6 +106,22 @@ namespace CHECK_EQUAL(1, DataM::get_instance_count()); } + //************************************************************************* + TEST(test_moveable) + { + etl::optional data(std::move(DataM(1))); + CHECK_EQUAL(1U, data.value().value); + CHECK(bool(data)); + + data = std::move(etl::optional(std::move(DataM(2)))); + CHECK_EQUAL(2U, data.value().value); + CHECK(bool(data)); + + etl::optional data2(etl::move(data)); + CHECK_EQUAL(2U, data2.value().value); + CHECK(bool(data2)); + } + //************************************************************************* TEST(test_nullopt) { diff --git a/test/test_packet.cpp b/test/test_packet.cpp index 44def9cf..baa294f7 100644 --- a/test/test_packet.cpp +++ b/test/test_packet.cpp @@ -41,6 +41,7 @@ namespace { base(int v_) : v(v_) + , was_moved(false) { } @@ -50,9 +51,12 @@ namespace virtual int value() const = 0; + bool was_moved; + protected: const int v; + }; struct not_base @@ -69,6 +73,18 @@ namespace { } + derived_1(const derived_1& other) + : base(other.value()) + { + was_moved = false; + } + + derived_1(derived_1&& other) + : base(other.value()) + { + was_moved = true; + } + int value() const { return v; @@ -84,6 +100,18 @@ namespace { } + derived_2(const derived_2& other) + : base(other.value()) + { + was_moved = false; + } + + derived_2(derived_2&& other) + : base(other.value()) + { + was_moved = true; + } + int value() const { return v; @@ -104,8 +132,11 @@ namespace derived_1 d1(1); derived_2 d2(2); - packet1_t p11(d1); - packet1_t p12(d2); + packet1_t p11(d1); // Uses copy constructor + CHECK(p11.get().was_moved == false); + + packet1_t p12(derived_2(2)); // Uses move constructor + CHECK(p12.get().was_moved == true); base* b; b = &p11.get(); @@ -125,15 +156,18 @@ namespace { derived_1 d1(1); derived_2 d2(2); + derived_1 d3(3); packet1_t p(d1); - base* b; b = &p.get(); CHECK_EQUAL(d1.value(), b->value()); p = d2; CHECK_EQUAL(d2.value(), b->value()); + + p = derived_1(3); + CHECK_EQUAL(d3.value(), b->value()); } //************************************************************************* diff --git a/test/test_queue.cpp b/test/test_queue.cpp index da1a6eb1..367d11a2 100644 --- a/test/test_queue.cpp +++ b/test/test_queue.cpp @@ -31,6 +31,7 @@ SOFTWARE. #include #include "etl/queue.h" +#include "data.h" namespace { @@ -73,6 +74,8 @@ namespace char* p; }; + using ItemM = TestDataM; + SUITE(test_queue) { //************************************************************************* @@ -97,6 +100,39 @@ namespace } } + //************************************************************************* + TEST(test_move_constructor) + { + etl::queue queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + etl::queue queue2(std::move(queue)); + + CHECK(queue.size() == queue2.size()); + + while (!queue.empty()) + { + CHECK(!bool(queue.front())); // Queue1 entry is invalid. + CHECK(bool(queue2.front())); // Queue2 value is valid. + queue.pop(); + queue2.pop(); + } + } + //************************************************************************* TEST(test_delete_via_iqueue) { diff --git a/test/test_queue_mpmc_mutex.cpp b/test/test_queue_mpmc_mutex.cpp index a1a74c3c..80e16143 100644 --- a/test/test_queue_mpmc_mutex.cpp +++ b/test/test_queue_mpmc_mutex.cpp @@ -37,6 +37,8 @@ SOFTWARE. #include "etl/queue_mpmc_mutex.h" +#include "data.h" + #if ETL_HAS_MUTEX #if defined(ETL_COMPILER_MICROSOFT) @@ -76,6 +78,8 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } + using ItemM = TestDataM; + // std::ostream& operator <<(std::ostream& os, const Data& data) // { // os << data.a << " " << data.b << " " << data.c << " " << data.d; @@ -145,6 +149,41 @@ namespace CHECK(!queue.pop(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_mpmc_mutex queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_mpmc_mutex_small.cpp b/test/test_queue_mpmc_mutex_small.cpp index db8c0733..2042841f 100644 --- a/test/test_queue_mpmc_mutex_small.cpp +++ b/test/test_queue_mpmc_mutex_small.cpp @@ -37,6 +37,8 @@ SOFTWARE. #include "etl/queue_mpmc_mutex.h" +#include "data.h" + #if ETL_HAS_MUTEX #if defined(ETL_COMPILER_MICROSOFT) @@ -81,6 +83,8 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } + using ItemM = TestDataM; + // std::ostream& operator <<(std::ostream& os, const Data& data) // { // os << data.a << " " << data.b << " " << data.c << " " << data.d; @@ -150,6 +154,41 @@ namespace CHECK(!queue.pop(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_mpmc_mutex queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_multiple_emplace) { diff --git a/test/test_queue_spsc_atomic.cpp b/test/test_queue_spsc_atomic.cpp index 753b4a34..7ffcef2a 100644 --- a/test/test_queue_spsc_atomic.cpp +++ b/test/test_queue_spsc_atomic.cpp @@ -34,6 +34,8 @@ SOFTWARE. #include "etl/queue_spsc_atomic.h" +#include "data.h" + #if ETL_HAS_ATOMIC #if defined(ETL_COMPILER_MICROSOFT) @@ -73,6 +75,8 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } + using ItemM = TestDataM; + SUITE(test_queue_atomic) { //************************************************************************* @@ -135,6 +139,41 @@ namespace CHECK(!queue.pop(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_spsc_atomic queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_size_push_pop_iqueue) { diff --git a/test/test_queue_spsc_atomic_small.cpp b/test/test_queue_spsc_atomic_small.cpp index e368527b..1f050c98 100644 --- a/test/test_queue_spsc_atomic_small.cpp +++ b/test/test_queue_spsc_atomic_small.cpp @@ -34,6 +34,8 @@ SOFTWARE. #include "etl/queue_spsc_atomic.h" +#include "data.h" + #if ETL_HAS_ATOMIC #if defined(ETL_COMPILER_MICROSOFT) @@ -78,6 +80,8 @@ namespace typedef etl::queue_spsc_atomic QueueInt254; + using ItemM = TestDataM; + SUITE(test_queue_atomic) { //************************************************************************* @@ -140,6 +144,41 @@ namespace CHECK(!queue.pop(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_spsc_atomic queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_size_push_pop_iqueue) { diff --git a/test/test_queue_spsc_isr.cpp b/test/test_queue_spsc_isr.cpp index 223e42ac..b618b9af 100644 --- a/test/test_queue_spsc_isr.cpp +++ b/test/test_queue_spsc_isr.cpp @@ -38,6 +38,8 @@ SOFTWARE. #include #endif +#include "data.h" + #define REALTIME_TEST 0 namespace @@ -98,6 +100,8 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } + using ItemM = TestDataM; + SUITE(test_queue_isr) { //************************************************************************* @@ -223,6 +227,41 @@ namespace CHECK(!queue.pop_from_isr(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_spsc_isr queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_size_push_pop_iqueue) { diff --git a/test/test_queue_spsc_isr_small.cpp b/test/test_queue_spsc_isr_small.cpp index a4bf7df9..9a8efb5d 100644 --- a/test/test_queue_spsc_isr_small.cpp +++ b/test/test_queue_spsc_isr_small.cpp @@ -38,6 +38,8 @@ SOFTWARE. #include #endif +#include "data.h" + #define REALTIME_TEST 0 namespace @@ -103,6 +105,8 @@ namespace typedef etl::queue_spsc_isr QueueInt255; + using ItemM = TestDataM; + SUITE(test_queue_isr) { //************************************************************************* @@ -228,6 +232,41 @@ namespace CHECK(!queue.pop_from_isr(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_spsc_isr queue; + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_size_push_pop_iqueue) { diff --git a/test/test_queue_spsc_locked.cpp b/test/test_queue_spsc_locked.cpp index d942bdf4..bb72874c 100644 --- a/test/test_queue_spsc_locked.cpp +++ b/test/test_queue_spsc_locked.cpp @@ -39,6 +39,8 @@ SOFTWARE. #include #endif +#include "data.h" + #define REALTIME_TEST 0 namespace @@ -101,6 +103,8 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } + using ItemM = TestDataM; + SUITE(test_queue_locked) { //************************************************************************* @@ -226,6 +230,41 @@ namespace CHECK(!queue.pop_from_unlocked(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_spsc_locked queue(lock, unlock); + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_size_push_pop_iqueue) { diff --git a/test/test_queue_spsc_locked_small.cpp b/test/test_queue_spsc_locked_small.cpp index c6352a6b..6f58bd05 100644 --- a/test/test_queue_spsc_locked_small.cpp +++ b/test/test_queue_spsc_locked_small.cpp @@ -38,6 +38,8 @@ SOFTWARE. #include #endif +#include "data.h" + #define REALTIME_TEST 0 namespace @@ -105,6 +107,8 @@ namespace typedef etl::queue_spsc_locked QueueInt255; + using ItemM = TestDataM; + SUITE(test_queue_locked) { //************************************************************************* @@ -230,6 +234,41 @@ namespace CHECK(!queue.pop_from_unlocked(i)); } + //************************************************************************* + TEST(test_move_push_pop) + { + etl::queue_spsc_locked queue(lock, unlock); + + ItemM p1(1); + ItemM p2(2); + ItemM p3(3); + ItemM p4(4); + + queue.push(std::move(p1)); + queue.push(std::move(p2)); + queue.push(std::move(p3)); + queue.push(std::move(p4)); + + CHECK(!bool(p1)); + CHECK(!bool(p2)); + CHECK(!bool(p3)); + CHECK(!bool(p4)); + + ItemM pr(0); + + queue.pop(std::move(pr)); + CHECK_EQUAL(1, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(2, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(3, pr.value); + + queue.pop(std::move(pr)); + CHECK_EQUAL(4, pr.value); + } + //************************************************************************* TEST(test_size_push_pop_iqueue) { diff --git a/test/test_set.cpp b/test/test_set.cpp index 52e472e6..360dfbcb 100755 --- a/test/test_set.cpp +++ b/test/test_set.cpp @@ -38,22 +38,27 @@ SOFTWARE. #include "etl/set.h" +#include "data.h" + static const size_t MAX_SIZE = 10; #define TEST_GREATER_THAN #ifdef TEST_GREATER_THAN -typedef etl::set > Data; -typedef etl::iset > IData; -typedef std::set > Compare_Data; +using Data = etl::set>; +using IData = etl::iset>; +using Compare_Data = std::set>; #else -typedef etl::set > Data; -typedef std::set > Compare_Data; +using Data = etl::set>; +using Compare_Data = std::set>; #endif -typedef Data::iterator Data_iterator; -typedef Data::const_iterator Data_const_iterator; -typedef Compare_Data::iterator Compare_Data_iterator; -typedef Compare_Data::const_iterator Compare_Data_const_iterator; +using ItemM = TestDataM; +using DataM = etl::set; + +using Data_iterator = Data::iterator; +using Data_const_iterator = Data::const_iterator; +using Compare_Data_iterator = Compare_Data::iterator; +using Compare_Data_const_iterator = Compare_Data::const_iterator; //************************************************************************* static std::ostream& operator << (std::ostream& os, const Data_iterator& it) @@ -229,6 +234,53 @@ namespace CHECK(data.begin() == data.end()); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_constructor) + { + Compare_Data compare_data(initial_data.begin(), initial_data.end()); + Data data1(compare_data.begin(), compare_data.end()); + Data data2(data1); + + CHECK_EQUAL(initial_data.size(), data1.size()); + CHECK(data1.size() == data2.size()); + + bool isEqual = false; + + isEqual = Check_Equal(data1.begin(), + data1.end(), + compare_data.begin()); + CHECK(isEqual); + + isEqual = Check_Equal(data2.begin(), + data2.end(), + compare_data.begin()); + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_constructor) + { + DataM data1; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data1.insert(etl::move(d1)); + data1.insert(etl::move(d2)); + data1.insert(etl::move(d3)); + data1.insert(ItemM(4)); + + DataM data2(std::move(data1)); + + CHECK(!data1.empty()); // Move does not clear the source. + + CHECK_EQUAL(1, ItemM(1).value); + CHECK_EQUAL(2, ItemM(2).value); + CHECK_EQUAL(3, ItemM(3).value); + CHECK_EQUAL(4, ItemM(4).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_destruct_via_iset) { @@ -316,6 +368,32 @@ namespace CHECK(isEqual); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_move_assignment) + { + DataM data1; + + ItemM d1(1); + ItemM d2(2); + ItemM d3(3); + + data1.insert(etl::move(d1)); + data1.insert(etl::move(d2)); + data1.insert(etl::move(d3)); + data1.insert(ItemM(4)); + + DataM data2; + + data2 = std::move(data1); + + CHECK(!data1.empty()); // Move does not clear the source. + + CHECK_EQUAL(1, ItemM(1).value); + CHECK_EQUAL(2, ItemM(2).value); + CHECK_EQUAL(3, ItemM(3).value); + CHECK_EQUAL(4, ItemM(4).value); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index 3c718dae..c0ec285f 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -598,6 +598,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -605,6 +606,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -612,6 +614,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -619,6 +622,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -626,6 +630,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -633,6 +638,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -640,6 +646,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -647,20 +654,31 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); + CHECK((etl::is_same::type>::value)); + CHECK((etl::is_same::reference>::value)); + CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); + CHECK((etl::is_same::pointer>::value)); + CHECK((etl::is_same::const_pointer>::value)); + CHECK((etl::is_same::const_pointer_const>::value)); + CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); - CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -668,6 +686,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -675,6 +694,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -682,6 +702,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -689,6 +710,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -696,6 +718,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); @@ -703,6 +726,7 @@ namespace CHECK((etl::is_same::type>::value)); CHECK((etl::is_same::reference>::value)); CHECK((etl::is_same::const_reference>::value)); + CHECK((etl::is_same::rvalue_reference>::value)); CHECK((etl::is_same::pointer>::value)); CHECK((etl::is_same::const_pointer>::value)); CHECK((etl::is_same::const_pointer_const>::value)); diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 7b367842..dd121d3c 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -30,6 +30,8 @@ SOFTWARE. #include "etl/utility.h" +#include "data.h" + namespace { bool nonConstCalled; @@ -44,6 +46,9 @@ namespace { constCalled = true; } + + using ItemM1 = TestDataM; + using ItemM2 = TestDataM; } namespace @@ -68,6 +73,15 @@ namespace CHECK_EQUAL(2.3, p1.second); } + //************************************************************************* + TEST(test_pair_move_parameter_construct) + { + etl::pair p1(1, 2.3); + + CHECK_EQUAL(1, p1.first.value); + CHECK_EQUAL(2.3, p1.second.value); + } + //************************************************************************* TEST(test_pair_copy_construct) { @@ -78,6 +92,19 @@ namespace CHECK_EQUAL(p1.second, p2.second); } + //************************************************************************* + TEST(test_pair_move_construct) + { + etl::pair p1(1, 2.3); + etl::pair p2(std::move(p1)); + + CHECK(!bool(p1.first)); + CHECK(!bool(p1.second)); + + CHECK_EQUAL(1, p2.first.value); + CHECK_EQUAL(2.3, p2.second.value); + } + //************************************************************************* TEST(test_pair_copy_construct_alternate) { @@ -99,6 +126,18 @@ namespace CHECK_EQUAL(p1.second, p2.second); } + //************************************************************************* + TEST(test_make_pair_move) + { + etl::pair p1(1, 2.3); + etl::pair p2(0, 0); + + p2 = etl::make_pair(std::move(ItemM1(1)), std::move(ItemM2(2.3))); + + CHECK_EQUAL(p1.first, p2.first); + CHECK_EQUAL(p1.second, p2.second); + } + //************************************************************************* TEST(test_pair_swap_member) { diff --git a/test/vs2017/.vs/etl/v15/.gitignore b/test/vs2017/.vs/etl/v15/.gitignore new file mode 100644 index 00000000..83235bb7 --- /dev/null +++ b/test/vs2017/.vs/etl/v15/.gitignore @@ -0,0 +1 @@ +*.VC.opendb diff --git a/test/vs2017/Debug No Unit Tests/.gitignore b/test/vs2017/Debug No Unit Tests/.gitignore new file mode 100644 index 00000000..b99f5c84 --- /dev/null +++ b/test/vs2017/Debug No Unit Tests/.gitignore @@ -0,0 +1,2 @@ +*.new.obj.enc +*.idb diff --git a/test/vs2017/Debug No Unit Tests/etl.tlog/.gitignore b/test/vs2017/Debug No Unit Tests/etl.tlog/.gitignore new file mode 100644 index 00000000..7839d155 --- /dev/null +++ b/test/vs2017/Debug No Unit Tests/etl.tlog/.gitignore @@ -0,0 +1,2 @@ +*.1.tlog +*.lastbuildstate diff --git a/test/vs2017/DebugNoSTL/.gitignore b/test/vs2017/DebugNoSTL/.gitignore new file mode 100644 index 00000000..b883f1fd --- /dev/null +++ b/test/vs2017/DebugNoSTL/.gitignore @@ -0,0 +1 @@ +*.exe From 31bd5b8774e83aee5d604f49c49f98cfb5810762 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 11 Feb 2020 19:40:48 +0100 Subject: [PATCH 3/5] Merge remote-tracking branch 'origin/development' From e6617dc7e7162be20c9cd460870e5e314140ebb7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 12 Feb 2020 09:40:20 +0100 Subject: [PATCH 4/5] Merge remote-tracking branch 'origin/development' # Conflicts: # include/etl/version.h # library.json # library.properties # support/Release notes.txt --- include/etl/experimental/atomic.h | 56 ------------------------- include/etl/{ => experimental}/icache.h | 0 include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 5 +++ test/vs2017/Debug LLVM/.gitignore | 1 + 7 files changed, 9 insertions(+), 59 deletions(-) delete mode 100644 include/etl/experimental/atomic.h rename include/etl/{ => experimental}/icache.h (100%) create mode 100644 test/vs2017/Debug LLVM/.gitignore diff --git a/include/etl/experimental/atomic.h b/include/etl/experimental/atomic.h deleted file mode 100644 index 48669852..00000000 --- a/include/etl/experimental/atomic.h +++ /dev/null @@ -1,56 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2017 jwellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef __ETL_ATOMIC__ -#define __ETL_ATOMIC__ - -#include "platform.h" - -#if ETL_ATOMIC_SUPPORTED == 1 - #include - - namespace etl - { - typedef std::atomic atomic_uint32_t; - } - #define ETL_CPP11_ATOMIC_AVAILABLE 1 -#elif defined(ETL_COMPILER_ARM) - #include "atomic/atomic_arm.h" - #define ETL_ETL_ATOMIC_AVAILABLE 1 -#elif defined(ETL_COMPILER_GCC) - #include "atomic/atomic_gcc.h" - #define ETL_ATOMIC_AVAILABLE 1 -#elif defined(ETL_COMPILER_MSVC) - #include "atomic/atomic_windows.h" - #define ETL_ATOMIC_AVAILABLE 1 -#else - #warning NO ATOMIC SUPPORT DEFINED! - #define ETL_ATOMIC_AVAILABLE 0 -#endif - -#endif diff --git a/include/etl/icache.h b/include/etl/experimental/icache.h similarity index 100% rename from include/etl/icache.h rename to include/etl/experimental/icache.h diff --git a/include/etl/version.h b/include/etl/version.h index 9d687c0c..1af2851f 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 16 #define ETL_VERSION_MINOR 4 -#define ETL_VERSION_PATCH 0 +#define ETL_VERSION_PATCH 1 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 83d58cc0..c263db8b 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "16.4.0", + "version": "16.4.1", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 9837f2dd..a773a8de 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=16.4.0 +version=16.4.1 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 28f60f6a..4924c077 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,8 @@ +=============================================================================== +16.4.1 +Moved icache.h to 'experimental' folder. +Removed atomic.h from 'experimental' folder. + =============================================================================== 16.4.0 Added rvalue references and 'move' API to all containers, except etl::priority_queue diff --git a/test/vs2017/Debug LLVM/.gitignore b/test/vs2017/Debug LLVM/.gitignore new file mode 100644 index 00000000..b883f1fd --- /dev/null +++ b/test/vs2017/Debug LLVM/.gitignore @@ -0,0 +1 @@ +*.exe From 5cdcc8d4c62c792973cfcf52e4cf22fad8a25f18 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 18 Feb 2020 10:45:09 +0100 Subject: [PATCH 5/5] Fix etl::pair error and warning --- include/etl/algorithm.h | 2 ++ include/etl/flat_multimap.h | 1 + include/etl/indirect_vector.h | 2 +- include/etl/memory.h | 2 +- include/etl/pool.h | 2 +- include/etl/priority_queue.h | 2 +- include/etl/stack.h | 3 +-- include/etl/utility.h | 8 ++++---- include/etl/variant.h | 1 + include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- support/Release notes.txt | 4 ++++ test/vs2017/DebugLLVMNoSTL/.gitignore | 1 + 14 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 test/vs2017/DebugLLVMNoSTL/.gitignore diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 31b0b0fc..6a2714ec 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -2048,6 +2048,7 @@ namespace etl return std::is_permutation(begin1, end1, begin2, predicate); } + #if ETL_CPP14_SUPPORTED //*************************************************************************** /// is_permutation ///\ingroup algorithm @@ -2078,6 +2079,7 @@ namespace etl { return std::is_permutation(begin1, end1, begin2, end2, predicate); } + #endif #endif #if defined(ETL_NO_STL) || !ETL_CPP11_SUPPORTED diff --git a/include/etl/flat_multimap.h b/include/etl/flat_multimap.h index e25588fd..f7955984 100644 --- a/include/etl/flat_multimap.h +++ b/include/etl/flat_multimap.h @@ -36,6 +36,7 @@ SOFTWARE. #include "platform.h" #include "reference_flat_multimap.h" #include "pool.h" +#include "utility.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) #include diff --git a/include/etl/indirect_vector.h b/include/etl/indirect_vector.h index 09511ddb..102583bf 100644 --- a/include/etl/indirect_vector.h +++ b/include/etl/indirect_vector.h @@ -35,7 +35,7 @@ SOFTWARE. #include "vector.h" #include "pool.h" #include "iterator.h" -#include "iterator.h" +#include "utility.h" #include "functional.h" #if ETL_CPP11_SUPPORTED && !defined(ETL_STLPORT) && !defined(ETL_NO_STL) diff --git a/include/etl/memory.h b/include/etl/memory.h index ad6b6aee..5b59ce90 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -34,8 +34,8 @@ SOFTWARE. #include "platform.h" #include "algorithm.h" #include "type_traits.h" - #include "iterator.h" +#include "utility.h" #include diff --git a/include/etl/pool.h b/include/etl/pool.h index 8f051420..9f8fba81 100644 --- a/include/etl/pool.h +++ b/include/etl/pool.h @@ -37,7 +37,7 @@ SOFTWARE. #include "algorithm.h" #include "iterator.h" - +#include "utility.h" #include "error_handler.h" #include "alignment.h" #include "array.h" diff --git a/include/etl/priority_queue.h b/include/etl/priority_queue.h index 8f1174ed..2803139e 100644 --- a/include/etl/priority_queue.h +++ b/include/etl/priority_queue.h @@ -36,8 +36,8 @@ SOFTWARE. #include "platform.h" #include "algorithm.h" +#include "utility.h" #include "functional.h" - #include "container.h" #include "vector.h" #include "type_traits.h" diff --git a/include/etl/stack.h b/include/etl/stack.h index b0e5d351..26a9c398 100644 --- a/include/etl/stack.h +++ b/include/etl/stack.h @@ -37,9 +37,8 @@ SOFTWARE. #include #include "platform.h" - #include "algorithm.h" - +#include "utility.h" #include "container.h" #include "alignment.h" #include "array.h" diff --git a/include/etl/utility.h b/include/etl/utility.h index a5f1af4e..3b79f30a 100644 --- a/include/etl/utility.h +++ b/include/etl/utility.h @@ -132,7 +132,7 @@ namespace etl swap(second, other.second); } - pair& operator =(const pair& other) + pair& operator =(const pair& other) { first = other.first; second = other.second; @@ -141,7 +141,7 @@ namespace etl } template - pair& operator =(const pair& other) + pair& operator =(const pair& other) { first = other.first; second = other.second; @@ -150,7 +150,7 @@ namespace etl } #if ETL_CPP11_SUPPORTED - pair& operator =(pair&& other) + pair& operator =(pair&& other) { first = etl::move(other.first); second = etl::move(other.second); @@ -159,7 +159,7 @@ namespace etl } template - pair& operator =(pair&& other) + pair& operator =(pair&& other) { first = etl::move(other.first); second = etl::move(other.second); diff --git a/include/etl/variant.h b/include/etl/variant.h index 624c2310..6ceb9c46 100644 --- a/include/etl/variant.h +++ b/include/etl/variant.h @@ -36,6 +36,7 @@ SOFTWARE. #include #include "platform.h" +#include "utility.h" #include "array.h" #include "largest.h" #include "exception.h" diff --git a/include/etl/version.h b/include/etl/version.h index 1af2851f..94fa8d22 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 16 #define ETL_VERSION_MINOR 4 -#define ETL_VERSION_PATCH 1 +#define ETL_VERSION_PATCH 2 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index c263db8b..99059fc2 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "16.4.1", + "version": "16.4.2", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index a773a8de..124bb891 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=16.4.1 +version=16.4.2 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/support/Release notes.txt b/support/Release notes.txt index 4924c077..96083f41 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +16.4.2 +Fix etl::pair error and warning. + =============================================================================== 16.4.1 Moved icache.h to 'experimental' folder. diff --git a/test/vs2017/DebugLLVMNoSTL/.gitignore b/test/vs2017/DebugLLVMNoSTL/.gitignore new file mode 100644 index 00000000..b883f1fd --- /dev/null +++ b/test/vs2017/DebugLLVMNoSTL/.gitignore @@ -0,0 +1 @@ +*.exe