From 9c94fb3034a32d43c1b7d4732bc30d3b49ced045 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 6 Feb 2020 12:06:08 +0000 Subject: [PATCH] Merge remote-tracking branch 'origin/feature/rvalue-references' into development # Conflicts: # include/etl/flat_map.h # include/etl/flat_multimap.h # include/etl/flat_multiset.h # include/etl/flat_set.h # include/etl/queue.h # include/etl/queue_mpmc_mutex.h # include/etl/queue_spsc_atomic.h # include/etl/queue_spsc_isr.h # include/etl/queue_spsc_locked.h # test/test_flat_map.cpp # test/test_flat_multimap.cpp # test/test_flat_multiset.cpp # test/test_flat_set.cpp --- include/etl/algorithm.h | 116 ++++++-- include/etl/array.h | 18 +- include/etl/deque.h | 52 ++-- include/etl/flat_map.h | 2 - include/etl/flat_multimap.h | 2 - include/etl/flat_multiset.h | 2 - include/etl/flat_set.h | 2 - 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/queue.h | 2 + include/etl/queue_mpmc_mutex.h | 2 + include/etl/queue_spsc_atomic.h | 2 + include/etl/queue_spsc_isr.h | 4 + include/etl/queue_spsc_locked.h | 4 + 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/vector.h | 36 +-- test/test_array.cpp | 6 - test/test_deque.cpp | 41 +++ test/test_flat_map.cpp | 2 +- test/test_flat_multimap.cpp | 2 +- test/test_flat_multiset.cpp | 2 +- test/test_flat_set.cpp | 2 +- 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 | 29 +- test/test_set.cpp | 96 ++++++- test/test_type_traits.cpp | 26 +- test/vs2017/.vs/etl/v15/.gitignore | 1 + test/vs2017/Debug No Unit Tests/.gitignore | 2 + .../Debug No Unit Tests/etl.tlog/.gitignore | 2 + 41 files changed, 2011 insertions(+), 248 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 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/flat_map.h b/include/etl/flat_map.h index bbffd3c1..aa2c7b2c 100644 --- a/include/etl/flat_map.h +++ b/include/etl/flat_map.h @@ -828,8 +828,6 @@ namespace etl { this->insert(etl::move(*first++)); } - - rhs.clear(); } } #endif diff --git a/include/etl/flat_multimap.h b/include/etl/flat_multimap.h index 79c607fb..e25588fd 100644 --- a/include/etl/flat_multimap.h +++ b/include/etl/flat_multimap.h @@ -734,8 +734,6 @@ namespace etl { this->insert(etl::move(*first++)); } - - rhs.clear(); } } #endif diff --git a/include/etl/flat_multiset.h b/include/etl/flat_multiset.h index eebb6f02..9fbb870a 100644 --- a/include/etl/flat_multiset.h +++ b/include/etl/flat_multiset.h @@ -684,8 +684,6 @@ namespace etl { this->insert(etl::move(*first++)); } - - rhs.clear(); } } #endif diff --git a/include/etl/flat_set.h b/include/etl/flat_set.h index f3545e12..1bdfb791 100644 --- a/include/etl/flat_set.h +++ b/include/etl/flat_set.h @@ -771,8 +771,6 @@ namespace etl { this->insert(etl::move(*first++)); } - - rhs.clear(); } } #endif 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/queue.h b/include/etl/queue.h index c2e6ceb1..c89b1cf7 100644 --- a/include/etl/queue.h +++ b/include/etl/queue.h @@ -255,7 +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. diff --git a/include/etl/queue_mpmc_mutex.h b/include/etl/queue_mpmc_mutex.h index b57f4747..004684a6 100644 --- a/include/etl/queue_mpmc_mutex.h +++ b/include/etl/queue_mpmc_mutex.h @@ -145,7 +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; diff --git a/include/etl/queue_spsc_atomic.h b/include/etl/queue_spsc_atomic.h index ae515449..a50176c6 100644 --- a/include/etl/queue_spsc_atomic.h +++ b/include/etl/queue_spsc_atomic.h @@ -198,7 +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; diff --git a/include/etl/queue_spsc_isr.h b/include/etl/queue_spsc_isr.h index 114ac9b8..408d4985 100644 --- a/include/etl/queue_spsc_isr.h +++ b/include/etl/queue_spsc_isr.h @@ -59,7 +59,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 //************************************************************************* /// Push a value to the queue from an ISR. @@ -474,7 +476,9 @@ namespace etl 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. //************************************************************************* diff --git a/include/etl/queue_spsc_locked.h b/include/etl/queue_spsc_locked.h index 887a37ba..c0e4dca0 100644 --- a/include/etl/queue_spsc_locked.h +++ b/include/etl/queue_spsc_locked.h @@ -60,7 +60,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 //************************************************************************* /// Push a value to the queue from an ISR. @@ -471,7 +473,9 @@ namespace etl 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. //************************************************************************* 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/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/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 201698cb..e322ac75 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -188,6 +188,47 @@ namespace 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 cc2c08a5..1029f6df 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -381,7 +381,7 @@ namespace DataM data2(std::move(data1)); - CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data1.size()); // Move does not clear the source. CHECK_EQUAL(4U, data2.size()); DataM::const_iterator itr = data2.begin(); diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index f9a9bcdd..0513e0c9 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -367,7 +367,7 @@ namespace DataM data2(std::move(data1)); - CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(5U, data1.size()); // Move does not clear the source. CHECK_EQUAL(5U, data2.size()); DataM::const_iterator itr = data2.begin(); diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index 93b1d8d0..ab89f887 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -330,7 +330,7 @@ namespace DataM data2(std::move(data1)); - CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(5U, data1.size()); // Move does not clear the source. CHECK_EQUAL(5U, data2.size()); DataM::iterator itr = data2.begin(); diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index aa38ed7f..2e47f4da 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -339,7 +339,7 @@ namespace DataM data2(std::move(data1)); - CHECK_EQUAL(0U, data1.size()); + CHECK_EQUAL(4U, data1.size()); // Move does not clear the source. CHECK_EQUAL(4U, data2.size()); DataM::iterator itr = data2.begin(); 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..33b23a94 100644 --- a/test/test_packet.cpp +++ b/test/test_packet.cpp @@ -69,6 +69,16 @@ namespace { } + derived_1(const derived_1& other) + : base(other.value()) + { + } + + derived_1(derived_1&& other) + : base(other.value()) + { + } + int value() const { return v; @@ -84,6 +94,16 @@ namespace { } + derived_2(const derived_2& other) + : base(other.value()) + { + } + + derived_2(derived_2&& other) + : base(other.value()) + { + } + int value() const { return v; @@ -104,8 +124,8 @@ namespace derived_1 d1(1); derived_2 d2(2); - packet1_t p11(d1); - packet1_t p12(d2); + packet1_t p11(d1); // Uses copy constructor + packet1_t p12(derived_2(2)); // Uses move constructor base* b; b = &p11.get(); @@ -125,15 +145,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_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/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