mirror of
https://github.com/ETLCPP/etl.git
synced 2026-07-30 08:16:19 +08:00
Add emplace() to etl::map and further containers (#1462)
This commit is contained in:
parent
6df8842a21
commit
04b7004110
@ -579,6 +579,163 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Inserts an element into the flat_map if the key does not exist.
|
||||
/// The mapped value is constructed from args only if insertion takes place.
|
||||
//*************************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, Args&&... args)
|
||||
{
|
||||
iterator i_element = lower_bound(key);
|
||||
|
||||
// Already exists?
|
||||
if ((i_element != end()) && !compare(key, i_element->first))
|
||||
{
|
||||
return ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_map_full));
|
||||
|
||||
// Create it.
|
||||
value_type* pvalue = storage.allocate<value_type>();
|
||||
::new ((void*)etl::addressof(pvalue->first)) key_type(key);
|
||||
::new ((void*)etl::addressof(pvalue->second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
return refmap_t::insert_at(i_element, *pvalue);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts an element into the flat_map if the key does not exist.
|
||||
/// The key is moved into the container if insertion takes place.
|
||||
//*************************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(rvalue_key_reference key, Args&&... args)
|
||||
{
|
||||
iterator i_element = lower_bound(key);
|
||||
|
||||
// Already exists?
|
||||
if ((i_element != end()) && !compare(key, i_element->first))
|
||||
{
|
||||
return ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_map_full));
|
||||
|
||||
// Create it.
|
||||
value_type* pvalue = storage.allocate<value_type>();
|
||||
::new ((void*)etl::addressof(pvalue->first)) key_type(etl::move(key));
|
||||
::new ((void*)etl::addressof(pvalue->second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
return refmap_t::insert_at(i_element, *pvalue);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts an element into the flat_map if the key does not exist.
|
||||
//*************************************************************************
|
||||
template <typename T1>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1)
|
||||
{
|
||||
iterator i_element = lower_bound(key);
|
||||
|
||||
// Already exists?
|
||||
if ((i_element != end()) && !compare(key, i_element->first))
|
||||
{
|
||||
return ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_map_full));
|
||||
|
||||
// Create it.
|
||||
value_type* pvalue = storage.allocate<value_type>();
|
||||
::new ((void*)etl::addressof(pvalue->first)) key_type(key);
|
||||
::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
return refmap_t::insert_at(i_element, *pvalue);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts an element into the flat_map if the key does not exist.
|
||||
//*************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1, const T2& value2)
|
||||
{
|
||||
iterator i_element = lower_bound(key);
|
||||
|
||||
// Already exists?
|
||||
if ((i_element != end()) && !compare(key, i_element->first))
|
||||
{
|
||||
return ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_map_full));
|
||||
|
||||
// Create it.
|
||||
value_type* pvalue = storage.allocate<value_type>();
|
||||
::new ((void*)etl::addressof(pvalue->first)) key_type(key);
|
||||
::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
return refmap_t::insert_at(i_element, *pvalue);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts an element into the flat_map if the key does not exist.
|
||||
//*************************************************************************
|
||||
template <typename T1, typename T2, typename T3>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1, const T2& value2, const T3& value3)
|
||||
{
|
||||
iterator i_element = lower_bound(key);
|
||||
|
||||
// Already exists?
|
||||
if ((i_element != end()) && !compare(key, i_element->first))
|
||||
{
|
||||
return ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_map_full));
|
||||
|
||||
// Create it.
|
||||
value_type* pvalue = storage.allocate<value_type>();
|
||||
::new ((void*)etl::addressof(pvalue->first)) key_type(key);
|
||||
::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2, value3);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
return refmap_t::insert_at(i_element, *pvalue);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Inserts an element into the flat_map if the key does not exist.
|
||||
//*************************************************************************
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
{
|
||||
iterator i_element = lower_bound(key);
|
||||
|
||||
// Already exists?
|
||||
if ((i_element != end()) && !compare(key, i_element->first))
|
||||
{
|
||||
return ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_map_full));
|
||||
|
||||
// Create it.
|
||||
value_type* pvalue = storage.allocate<value_type>();
|
||||
::new ((void*)etl::addressof(pvalue->first)) key_type(key);
|
||||
::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2, value3, value4);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
return refmap_t::insert_at(i_element, *pvalue);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
|
||||
@ -339,7 +339,23 @@ namespace etl
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(flat_set_full));
|
||||
if (full())
|
||||
{
|
||||
// A duplicate key does not require a free slot, so emplacing it is not
|
||||
// a capacity failure. Construct a temporary to obtain its key and only
|
||||
// emit flat_set_full if the key is not already present. This keeps
|
||||
// emplace consistent with insert when the set is full.
|
||||
value_type temp_value(etl::forward<Args>(args)...);
|
||||
iterator position = find(temp_value);
|
||||
|
||||
if (position == end())
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(flat_set_full));
|
||||
return ETL_OR_STD::pair<iterator, bool>(end(), false);
|
||||
}
|
||||
|
||||
return ETL_OR_STD::pair<iterator, bool>(position, false);
|
||||
}
|
||||
|
||||
ETL_OR_STD::pair<iterator, bool> result;
|
||||
|
||||
@ -360,7 +376,7 @@ namespace etl
|
||||
// Destroy it.
|
||||
pvalue->~value_type();
|
||||
storage.release(pvalue);
|
||||
result = ETL_OR_STD::pair<iterator, bool>(end(), false);
|
||||
result = ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@ -1319,6 +1319,188 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the map.
|
||||
/// Constructs the value_type in place from the given arguments.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_from_args(etl::forward<Args>(args)...);
|
||||
|
||||
// Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
|
||||
Node* inserted_node = insert_node(root_node, node);
|
||||
bool 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);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the map if the key does not exist.
|
||||
/// The mapped value is constructed from args only if insertion takes place.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, Args&&... args)
|
||||
{
|
||||
// Check if key already exists
|
||||
Node* found = find_node(root_node, key);
|
||||
if (found)
|
||||
{
|
||||
return ETL_OR_STD::make_pair(iterator(*this, found), false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_emplace(key, etl::forward<Args>(args)...);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_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), true);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the map if the key does not exist.
|
||||
/// The key is moved into the container if insertion takes place.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(rvalue_key_reference key, Args&&... args)
|
||||
{
|
||||
// Check if key already exists
|
||||
Node* found = find_node(root_node, key);
|
||||
if (found)
|
||||
{
|
||||
return ETL_OR_STD::make_pair(iterator(*this, found), false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_emplace(etl::move(key), etl::forward<Args>(args)...);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_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), true);
|
||||
}
|
||||
#else
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the map.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(const value_type& value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the map if the key does not exist.
|
||||
//*********************************************************************
|
||||
template <typename T1>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1)
|
||||
{
|
||||
// Check if key already exists
|
||||
Node* found = find_node(root_node, key);
|
||||
if (found)
|
||||
{
|
||||
return ETL_OR_STD::make_pair(iterator(*this, found), false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_emplace(key, value1);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_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), true);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the map if the key does not exist.
|
||||
//*********************************************************************
|
||||
template <typename T1, typename T2>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1, const T2& value2)
|
||||
{
|
||||
// Check if key already exists
|
||||
Node* found = find_node(root_node, key);
|
||||
if (found)
|
||||
{
|
||||
return ETL_OR_STD::make_pair(iterator(*this, found), false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_emplace(key, value1, value2);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_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), true);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the map if the key does not exist.
|
||||
//*********************************************************************
|
||||
template <typename T1, typename T2, typename T3>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1, const T2& value2, const T3& value3)
|
||||
{
|
||||
// Check if key already exists
|
||||
Node* found = find_node(root_node, key);
|
||||
if (found)
|
||||
{
|
||||
return ETL_OR_STD::make_pair(iterator(*this, found), false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_emplace(key, value1, value2, value3);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_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), true);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the map if the key does not exist.
|
||||
//*********************************************************************
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
{
|
||||
// Check if key already exists
|
||||
Node* found = find_node(root_node, key);
|
||||
if (found)
|
||||
{
|
||||
return ETL_OR_STD::make_pair(iterator(*this, found), false);
|
||||
}
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(map_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_emplace(key, value1, value2, value3, value4);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_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), true);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns an iterator pointing to the first element in the container
|
||||
/// whose key is not considered to go before the key provided or end()
|
||||
@ -1545,6 +1727,106 @@ namespace etl
|
||||
return *node;
|
||||
}
|
||||
|
||||
#if ETL_NOT_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node with the key and emplace args for the mapped value.
|
||||
//*************************************************************************
|
||||
template <typename... Args>
|
||||
Data_Node& allocate_data_node_emplace(const_key_reference key, Args&&... args)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
|
||||
::new ((void*)etl::addressof(node->value.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->value.second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node with a moved key and emplace args for the mapped value.
|
||||
//*************************************************************************
|
||||
template <typename... Args>
|
||||
Data_Node& allocate_data_node_emplace(rvalue_key_reference key, Args&&... args)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
|
||||
::new ((void*)etl::addressof(node->value.first)) key_type(etl::move(key));
|
||||
::new ((void*)etl::addressof(node->value.second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node by constructing the value_type from args.
|
||||
//*************************************************************************
|
||||
template <typename... Args>
|
||||
Data_Node& allocate_data_node_from_args(Args&&... args)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
::new (&node->value) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node with the key and emplace args for the mapped value.
|
||||
//*************************************************************************
|
||||
template <typename T1>
|
||||
Data_Node& allocate_data_node_emplace(const_key_reference key, const T1& value1)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
|
||||
::new ((void*)etl::addressof(node->value.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->value.second)) mapped_type(value1);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node with the key and emplace args for the mapped value.
|
||||
//*************************************************************************
|
||||
template <typename T1, typename T2>
|
||||
Data_Node& allocate_data_node_emplace(const_key_reference key, const T1& value1, const T2& value2)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
|
||||
::new ((void*)etl::addressof(node->value.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->value.second)) mapped_type(value1, value2);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node with the key and emplace args for the mapped value.
|
||||
//*************************************************************************
|
||||
template <typename T1, typename T2, typename T3>
|
||||
Data_Node& allocate_data_node_emplace(const_key_reference key, const T1& value1, const T2& value2, const T3& value3)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
|
||||
::new ((void*)etl::addressof(node->value.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->value.second)) mapped_type(value1, value2, value3);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node with the key and emplace args for the mapped value.
|
||||
//*************************************************************************
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
Data_Node& allocate_data_node_emplace(const_key_reference key, const T1& value1, const T2& value2, const T3& value3, const T4& value4)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
|
||||
::new ((void*)etl::addressof(node->value.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->value.second)) mapped_type(value1, value2, value3, value4);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -1368,6 +1368,35 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the multimap.
|
||||
//*********************************************************************
|
||||
iterator emplace(const_reference value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the multimap.
|
||||
/// Constructs the value_type in place from the given arguments.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(multimap_full));
|
||||
|
||||
// Get next available free node
|
||||
Data_Node& node = allocate_data_node_from_args(etl::forward<Args>(args)...);
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_node, node);
|
||||
|
||||
// Return iterator to new node location in tree
|
||||
return iterator(*this, inserted_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns an iterator pointing to the first element in the container
|
||||
/// whose key is not considered to go before the key provided or end()
|
||||
@ -1567,6 +1596,21 @@ namespace etl
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
|
||||
#if ETL_NOT_USING_STLPORT
|
||||
//*************************************************************************
|
||||
/// Allocate a Data_Node by constructing the value_type from args.
|
||||
//*************************************************************************
|
||||
template <typename... Args>
|
||||
Data_Node& allocate_data_node_from_args(Args&&... args)
|
||||
{
|
||||
Data_Node* node = allocate_data_node();
|
||||
::new (&node->value) const value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
return *node;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
|
||||
@ -1353,6 +1353,51 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the multiset.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(multiset_full));
|
||||
|
||||
// Construct the value
|
||||
Data_Node* p_node = allocate_data_node();
|
||||
::new ((void*)&p_node->value) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Obtain the inserted node
|
||||
Node* inserted_node = insert_node(root_node, *p_node);
|
||||
|
||||
return iterator(*this, inserted_node);
|
||||
}
|
||||
#else
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the multiset.
|
||||
//*********************************************************************
|
||||
iterator emplace(const_reference value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the multiset.
|
||||
//*********************************************************************
|
||||
template <typename T1>
|
||||
iterator emplace(const T1& value1)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(multiset_full));
|
||||
|
||||
Data_Node* p_node = allocate_data_node();
|
||||
::new ((void*)&p_node->value) value_type(value1);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
Node* inserted_node = insert_node(root_node, *p_node);
|
||||
return iterator(*this, inserted_node);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns an iterator pointing to the first element in the container
|
||||
/// whose key is not considered to go before the key provided or end()
|
||||
|
||||
@ -563,6 +563,18 @@ namespace etl
|
||||
return insert_at(i_element, value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the reference_flat_map.
|
||||
/// As the reference_flat_map stores references to externally owned
|
||||
/// objects, the value is not constructed in place but inserted by
|
||||
/// reference.
|
||||
///\param value The value to emplace.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(reference value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the reference_flat_map.
|
||||
/// If asserts or exceptions are enabled, emits flat_map_full if the
|
||||
|
||||
@ -485,6 +485,18 @@ namespace etl
|
||||
return insert_at(i_element, value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the reference_flat_multimap.
|
||||
/// As the reference_flat_multimap stores references to externally owned
|
||||
/// objects, the value is not constructed in place but inserted by
|
||||
/// reference.
|
||||
///\param value The value to emplace.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(value_type& value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the flat_multi.
|
||||
/// If asserts or exceptions are enabled, emits flat_map_full if the
|
||||
|
||||
@ -478,6 +478,18 @@ namespace etl
|
||||
return result;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the reference_flat_multiset.
|
||||
/// As the reference_flat_multiset stores references to externally owned
|
||||
/// objects, the value is not constructed in place but inserted by
|
||||
/// reference.
|
||||
///\param value The value to emplace.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(value_type& value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the reference_flat_multiset.
|
||||
/// If asserts or exceptions are enabled, emits reference_flat_multiset_full
|
||||
|
||||
@ -455,6 +455,18 @@ namespace etl
|
||||
return insert_at(i_element, value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the reference_flat_set.
|
||||
/// As the reference_flat_set stores references to externally owned
|
||||
/// objects, the value is not constructed in place but inserted by
|
||||
/// reference.
|
||||
///\param value The value to emplace.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(reference value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts a value to the reference_flat_set.
|
||||
/// If asserts or exceptions are enabled, emits reference_flat_set_full if
|
||||
|
||||
@ -1267,6 +1267,86 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the set.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
if (full())
|
||||
{
|
||||
// A duplicate key does not require a free node, so emplacing it is not
|
||||
// a capacity failure. Construct a temporary to obtain its key and only
|
||||
// emit set_full if the key is not already present. This keeps emplace
|
||||
// consistent with insert when the set is full.
|
||||
value_type temp_value(etl::forward<Args>(args)...);
|
||||
iterator position = find(temp_value);
|
||||
|
||||
if (position == end())
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(set_full));
|
||||
return ETL_OR_STD::make_pair(end(), false);
|
||||
}
|
||||
|
||||
return ETL_OR_STD::make_pair(position, false);
|
||||
}
|
||||
|
||||
// Construct the value
|
||||
Data_Node* p_node = allocate_data_node();
|
||||
::new ((void*)&p_node->value) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Obtain the inserted node (might be ETL_NULLPTR if node was a duplicate)
|
||||
Node* inserted_node = insert_node(root_node, *p_node);
|
||||
bool inserted = inserted_node == p_node;
|
||||
|
||||
return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
|
||||
}
|
||||
#else
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the set.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(const_reference value)
|
||||
{
|
||||
return insert(value);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the set.
|
||||
//*********************************************************************
|
||||
template <typename T1>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(const T1& value1)
|
||||
{
|
||||
if (full())
|
||||
{
|
||||
// A duplicate key does not require a free node, so emplacing it is not
|
||||
// a capacity failure. Construct a temporary to obtain its key and only
|
||||
// emit set_full if the key is not already present. This keeps emplace
|
||||
// consistent with insert when the set is full.
|
||||
value_type temp_value(value1);
|
||||
iterator position = find(temp_value);
|
||||
|
||||
if (position == end())
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(set_full));
|
||||
return ETL_OR_STD::make_pair(end(), false);
|
||||
}
|
||||
|
||||
return ETL_OR_STD::make_pair(position, false);
|
||||
}
|
||||
|
||||
Data_Node* p_node = allocate_data_node();
|
||||
::new ((void*)&p_node->value) value_type(value1);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
Node* inserted_node = insert_node(root_node, *p_node);
|
||||
bool inserted = inserted_node == p_node;
|
||||
|
||||
return ETL_OR_STD::make_pair(iterator(*this, inserted_node), inserted);
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Returns an iterator pointing to the first element in the container
|
||||
/// whose key is not considered to go before the key provided or end()
|
||||
|
||||
@ -1163,6 +1163,250 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the unordered_map.
|
||||
/// Constructs the value_type in place from the given arguments.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
ETL_OR_STD::pair<iterator, bool> result(end(), false);
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
|
||||
|
||||
// Construct the value in a temporary node to get the key for hashing.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair)) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
const_key_reference key = node->key_value_pair.first;
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(key);
|
||||
|
||||
// Get the bucket & bucket iterator.
|
||||
bucket_t* pbucket = pbuckets + index;
|
||||
bucket_t& bucket = *pbucket;
|
||||
|
||||
// The first one in the bucket?
|
||||
if (bucket.empty())
|
||||
{
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
|
||||
adjust_first_last_markers_after_insert(pbucket);
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
|
||||
result.second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step though the bucket looking for a place to insert.
|
||||
local_iterator inode_previous = bucket.before_begin();
|
||||
local_iterator inode = bucket.begin();
|
||||
|
||||
while (inode != bucket.end())
|
||||
{
|
||||
// Do we already have this key?
|
||||
if (key_equal_function(inode->key_value_pair.first, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Not already there?
|
||||
if (inode == bucket.end())
|
||||
{
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
|
||||
result.second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Duplicate found, destroy the node
|
||||
node->key_value_pair.~value_type();
|
||||
pnodepool->release(node);
|
||||
ETL_DECREMENT_DEBUG_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the unordered_map if the key does not exist.
|
||||
/// The mapped value is constructed from args only if insertion takes place.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(const_key_reference key, Args&&... args)
|
||||
{
|
||||
ETL_OR_STD::pair<iterator, bool> result(end(), false);
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(key);
|
||||
|
||||
// Get the bucket & bucket iterator.
|
||||
bucket_t* pbucket = pbuckets + index;
|
||||
bucket_t& bucket = *pbucket;
|
||||
|
||||
// The first one in the bucket?
|
||||
if (bucket.empty())
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
|
||||
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->key_value_pair.second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
|
||||
adjust_first_last_markers_after_insert(pbucket);
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
|
||||
result.second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step though the bucket looking for a place to insert.
|
||||
local_iterator inode_previous = bucket.before_begin();
|
||||
local_iterator inode = bucket.begin();
|
||||
|
||||
while (inode != bucket.end())
|
||||
{
|
||||
// Do we already have this key?
|
||||
if (key_equal_function(inode->key_value_pair.first, key))
|
||||
{
|
||||
// Found duplicate, return iterator to existing element
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode);
|
||||
return result;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Not already there, insert new element.
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
|
||||
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair.first)) key_type(key);
|
||||
::new ((void*)etl::addressof(node->key_value_pair.second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
|
||||
result.second = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Inserts an element into the unordered_map if the key does not exist.
|
||||
/// The key is moved into the container if insertion takes place.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> try_emplace(rvalue_key_reference key, Args&&... args)
|
||||
{
|
||||
ETL_OR_STD::pair<iterator, bool> result(end(), false);
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(key);
|
||||
|
||||
// Get the bucket & bucket iterator.
|
||||
bucket_t* pbucket = pbuckets + index;
|
||||
bucket_t& bucket = *pbucket;
|
||||
|
||||
// The first one in the bucket?
|
||||
if (bucket.empty())
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
|
||||
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair.first)) key_type(etl::move(key));
|
||||
::new ((void*)etl::addressof(node->key_value_pair.second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
|
||||
adjust_first_last_markers_after_insert(pbucket);
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
|
||||
result.second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step though the bucket looking for a place to insert.
|
||||
local_iterator inode_previous = bucket.before_begin();
|
||||
local_iterator inode = bucket.begin();
|
||||
|
||||
while (inode != bucket.end())
|
||||
{
|
||||
// Do we already have this key?
|
||||
if (key_equal_function(inode->key_value_pair.first, key))
|
||||
{
|
||||
// Found duplicate, return iterator to existing element
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode);
|
||||
return result;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Not already there, insert new element.
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_map_full));
|
||||
|
||||
// Get a new node.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair.first)) key_type(etl::move(key));
|
||||
::new ((void*)etl::addressof(node->key_value_pair.second)) mapped_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result.first = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
|
||||
result.second = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the unordered_map.
|
||||
//*********************************************************************
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(const_reference key_value_pair)
|
||||
{
|
||||
return insert(key_value_pair);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
|
||||
@ -687,10 +687,10 @@ namespace etl
|
||||
//*********************************************************************
|
||||
iterator insert(const_reference key_value_pair)
|
||||
{
|
||||
iterator result = end();
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
||||
|
||||
iterator result = end();
|
||||
|
||||
const_key_reference key = key_value_pair.first;
|
||||
|
||||
// Get the hash index.
|
||||
@ -759,10 +759,10 @@ namespace etl
|
||||
//*********************************************************************
|
||||
iterator insert(rvalue_reference key_value_pair)
|
||||
{
|
||||
iterator result = end();
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
||||
|
||||
iterator result = end();
|
||||
|
||||
const_key_reference key = key_value_pair.first;
|
||||
|
||||
// Get the hash index.
|
||||
@ -867,6 +867,80 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the unordered_multimap.
|
||||
/// Constructs the value_type in place from the given arguments.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
||||
|
||||
iterator result = end();
|
||||
|
||||
// Construct the value in a temporary node to get the key for hashing.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new ((void*)etl::addressof(node->key_value_pair)) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
const_key_reference key = node->key_value_pair.first;
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(key);
|
||||
|
||||
// Get the bucket & bucket iterator.
|
||||
bucket_t* pbucket = pbuckets + index;
|
||||
bucket_t& bucket = *pbucket;
|
||||
|
||||
// The first one in the bucket?
|
||||
if (bucket.empty())
|
||||
{
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
adjust_first_last_markers_after_insert(pbucket);
|
||||
|
||||
result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step though the bucket looking for a place to insert.
|
||||
local_iterator inode_previous = bucket.before_begin();
|
||||
local_iterator inode = bucket.begin();
|
||||
|
||||
while (inode != bucket.end())
|
||||
{
|
||||
// Do we already have this key?
|
||||
if (key_equal_function(inode->key_value_pair.first, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the unordered_multimap.
|
||||
//*********************************************************************
|
||||
iterator emplace(const_reference key_value_pair)
|
||||
{
|
||||
return insert(key_value_pair);
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
|
||||
@ -920,6 +920,71 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the unordered_multiset.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
iterator emplace(Args&&... args)
|
||||
{
|
||||
iterator result = end();
|
||||
|
||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multiset_full));
|
||||
|
||||
// Construct the value
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new (&node->key) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
key_parameter_t key = node->key;
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(key);
|
||||
|
||||
// Get the bucket & bucket iterator.
|
||||
bucket_t* pbucket = pbuckets + index;
|
||||
bucket_t& bucket = *pbucket;
|
||||
|
||||
// The first one in the bucket?
|
||||
if (bucket.empty())
|
||||
{
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
|
||||
result = iterator((pbuckets + number_of_buckets), pbucket, pbucket->begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step though the bucket looking for a place to insert.
|
||||
local_iterator inode_previous = bucket.before_begin();
|
||||
local_iterator inode = bucket.begin();
|
||||
|
||||
while (inode != bucket.end())
|
||||
{
|
||||
// Do we already have this key?
|
||||
if (key_equal_function(inode->key, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result = iterator((pbuckets + number_of_buckets), pbucket, inode_previous);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
|
||||
@ -980,6 +980,102 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
#if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT
|
||||
//*********************************************************************
|
||||
/// Emplaces a value to the unordered_set.
|
||||
//*********************************************************************
|
||||
template <typename... Args>
|
||||
ETL_OR_STD::pair<iterator, bool> emplace(Args&&... args)
|
||||
{
|
||||
ETL_OR_STD::pair<iterator, bool> result(end(), false);
|
||||
|
||||
if (full())
|
||||
{
|
||||
// A duplicate key does not require a free node, so emplacing it is not
|
||||
// a capacity failure. Construct a temporary to obtain its key and only
|
||||
// emit unordered_set_full if the key is not already present. This keeps
|
||||
// emplace consistent with insert when the unordered_set is full.
|
||||
value_type temp_value(etl::forward<Args>(args)...);
|
||||
iterator position = find(temp_value);
|
||||
|
||||
if (position == end())
|
||||
{
|
||||
ETL_ASSERT_FAIL(ETL_ERROR(unordered_set_full));
|
||||
return result;
|
||||
}
|
||||
|
||||
result.first = position;
|
||||
result.second = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Construct the value in a temporary to get the key for hashing.
|
||||
node_t* node = allocate_data_node();
|
||||
node->clear();
|
||||
::new (&node->key) value_type(etl::forward<Args>(args)...);
|
||||
ETL_INCREMENT_DEBUG_COUNT;
|
||||
|
||||
key_parameter_t key = node->key;
|
||||
|
||||
// Get the hash index.
|
||||
size_t index = get_bucket_index(key);
|
||||
|
||||
// Get the bucket & bucket iterator.
|
||||
bucket_t* pbucket = pbuckets + index;
|
||||
bucket_t& bucket = *pbucket;
|
||||
|
||||
// The first one in the bucket?
|
||||
if (bucket.empty())
|
||||
{
|
||||
// Just add the pointer to the bucket;
|
||||
bucket.insert_after(bucket.before_begin(), *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
|
||||
result.first = iterator(pbuckets + number_of_buckets, pbucket, pbucket->begin());
|
||||
result.second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Step though the bucket looking for a place to insert.
|
||||
local_iterator inode_previous = bucket.before_begin();
|
||||
local_iterator inode = bucket.begin();
|
||||
|
||||
while (inode != bucket.end())
|
||||
{
|
||||
// Do we already have this key?
|
||||
if (key_equal_function(inode->key, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
++inode_previous;
|
||||
++inode;
|
||||
}
|
||||
|
||||
// Not already there?
|
||||
if (inode == bucket.end())
|
||||
{
|
||||
// Add the node to the end of the bucket;
|
||||
bucket.insert_after(inode_previous, *node);
|
||||
adjust_first_last_markers_after_insert(&bucket);
|
||||
++inode_previous;
|
||||
|
||||
result.first = iterator(pbuckets + number_of_buckets, pbucket, inode_previous);
|
||||
result.second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Duplicate found, destroy the node
|
||||
node->key.~value_type();
|
||||
pnodepool->release(node);
|
||||
ETL_DECREMENT_DEBUG_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*********************************************************************
|
||||
/// Erases an element.
|
||||
///\param key The key to erase.
|
||||
|
||||
@ -981,6 +981,66 @@ namespace
|
||||
CHECK(!result.second);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_value)
|
||||
{
|
||||
Data1 data;
|
||||
|
||||
// Insert with an lvalue key (const_key_reference overload).
|
||||
int key0 = 0;
|
||||
ETL_OR_STD::pair<Data1::iterator, bool> result1 = data.try_emplace(key0, "0");
|
||||
CHECK(result1.second == true);
|
||||
CHECK(result1.first->first == 0);
|
||||
CHECK(result1.first->second.a == "0");
|
||||
|
||||
// Insert with an rvalue key (rvalue_key_reference overload).
|
||||
ETL_OR_STD::pair<Data1::iterator, bool> result2 = data.try_emplace(1, "1");
|
||||
CHECK(result2.second == true);
|
||||
CHECK(result2.first->first == 1);
|
||||
CHECK(result2.first->second.a == "1");
|
||||
|
||||
// Duplicate key: the mapped value must NOT be overwritten.
|
||||
ETL_OR_STD::pair<Data1::iterator, bool> result3 = data.try_emplace(0, "99");
|
||||
CHECK(result3.second == false);
|
||||
CHECK(result3.first->first == 0);
|
||||
CHECK(result3.first->second.a == "0");
|
||||
|
||||
CHECK_EQUAL(2U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_moved_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
MC m1("1");
|
||||
MC m2("2");
|
||||
|
||||
// Insert with a moved mapped value (lvalue key -> const_key_reference overload).
|
||||
int key1 = 1;
|
||||
ETL_OR_STD::pair<DataM::iterator, bool> result1 = data.try_emplace(key1, std::move(m1));
|
||||
CHECK(result1.second == true);
|
||||
CHECK(!bool(m1)); // m1 was moved from
|
||||
CHECK("1" == result1.first->second.value);
|
||||
|
||||
// Duplicate key (rvalue key literal -> rvalue_key_reference overload):
|
||||
// m2 must NOT be moved from.
|
||||
ETL_OR_STD::pair<DataM::iterator, bool> result2 = data.try_emplace(1, std::move(m2));
|
||||
CHECK(result2.second == false);
|
||||
CHECK(bool(m2)); // m2 was NOT moved
|
||||
CHECK("1" == result2.first->second.value);
|
||||
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_excess)
|
||||
{
|
||||
DataNDC data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_THROW(data.try_emplace(10, N10), etl::flat_map_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||
{
|
||||
|
||||
@ -709,6 +709,21 @@ namespace
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_moved_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
data.emplace(1, MC("1"));
|
||||
data.emplace(2, MC("2"));
|
||||
data.emplace(3, MC("3"));
|
||||
|
||||
CHECK("1" == data.find(1)->second.value);
|
||||
CHECK("2" == data.find(2)->second.value);
|
||||
CHECK("3" == data.find(3)->second.value);
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||
{
|
||||
|
||||
@ -728,6 +728,14 @@ namespace
|
||||
CHECK(isEqual);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_excess)
|
||||
{
|
||||
DataNDC data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_THROW(data.emplace(N10), etl::flat_multiset_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||
{
|
||||
|
||||
@ -754,6 +754,47 @@ namespace
|
||||
CHECK_EQUAL(compare.size(), data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_excess)
|
||||
{
|
||||
DataInt data(int_data.begin(), int_data.end());
|
||||
|
||||
CHECK_THROW(data.emplace(99), etl::flat_set_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_existing_value_when_full)
|
||||
{
|
||||
DataInt data;
|
||||
ETL_OR_STD::pair<DataInt::iterator, bool> data_result;
|
||||
|
||||
for (size_t i = 0; i < SIZE; ++i)
|
||||
{
|
||||
data.emplace(static_cast<int>(i));
|
||||
}
|
||||
|
||||
CHECK(data.full());
|
||||
|
||||
// Emplacing a new key when the set is full should throw etl::flat_set_full.
|
||||
CHECK_THROW(data.emplace(static_cast<int>(SIZE)), etl::flat_set_full);
|
||||
|
||||
// Emplacing an existing (duplicate) key when the set is full should not
|
||||
// throw; it should return an iterator to the existing element, matching
|
||||
// the behaviour of insert().
|
||||
for (size_t i = 0; i < SIZE; ++i)
|
||||
{
|
||||
data_result = data.emplace(static_cast<int>(i));
|
||||
|
||||
CHECK(data_result.first != data.end());
|
||||
CHECK_EQUAL(static_cast<int>(i), *data_result.first);
|
||||
CHECK(data_result.second == false);
|
||||
}
|
||||
|
||||
// The set must be unchanged.
|
||||
CHECK_EQUAL(SIZE, data.size());
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||
{
|
||||
|
||||
@ -808,6 +808,166 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::map_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
ETL_OR_STD::pair<Data::iterator, bool> data_result = data.emplace(std::string("0"), 0);
|
||||
compare_data.insert(ETL_OR_STD::make_pair(std::string("0"), 0));
|
||||
|
||||
// Check that the insertion was successful
|
||||
CHECK(data_result.first->first == std::string("0"));
|
||||
CHECK(data_result.first->second == 0);
|
||||
CHECK(data_result.second == true);
|
||||
|
||||
// Try adding a duplicate (should return iterator pointing to duplicate, inserted = false)
|
||||
data_result = data.emplace(std::string("0"), 1);
|
||||
|
||||
CHECK(data_result.first->first == std::string("0"));
|
||||
CHECK(data_result.first->second == 0);
|
||||
CHECK(data_result.second == false);
|
||||
|
||||
// Add more elements
|
||||
data.emplace(std::string("2"), 2);
|
||||
compare_data.insert(ETL_OR_STD::make_pair(std::string("2"), 2));
|
||||
|
||||
data.emplace(std::string("1"), 1);
|
||||
compare_data.insert(ETL_OR_STD::make_pair(std::string("1"), 1));
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.value_comp()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value_from_pair)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
Data::value_type pair0(std::string("0"), 0);
|
||||
Data::value_type pair1(std::string("1"), 1);
|
||||
Data::value_type pair2(std::string("2"), 2);
|
||||
|
||||
data.emplace(pair0);
|
||||
compare_data.insert(pair0);
|
||||
|
||||
data.emplace(pair1);
|
||||
compare_data.insert(pair1);
|
||||
|
||||
data.emplace(pair2);
|
||||
compare_data.insert(pair2);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.value_comp()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_moved_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
ItemM d1(1);
|
||||
ItemM d2(2);
|
||||
ItemM d3(3);
|
||||
|
||||
data.emplace(std::string("1"), etl::move(d1));
|
||||
data.emplace(std::string("2"), etl::move(d2));
|
||||
data.emplace(std::string("3"), etl::move(d3));
|
||||
data.emplace(std::string("4"), ItemM(4));
|
||||
|
||||
CHECK(!bool(d1));
|
||||
CHECK(!bool(d2));
|
||||
CHECK(!bool(d3));
|
||||
|
||||
CHECK(1 == data.at("1").value);
|
||||
CHECK(2 == data.at("2").value);
|
||||
CHECK(3 == data.at("3").value);
|
||||
CHECK(4 == data.at("4").value);
|
||||
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.value_comp()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_excess)
|
||||
{
|
||||
Data data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_THROW(data.emplace(std::string("10"), 10), etl::map_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_value)
|
||||
{
|
||||
Data data;
|
||||
|
||||
ETL_OR_STD::pair<Data::iterator, bool> result1 = data.try_emplace(std::string("0"), 0);
|
||||
CHECK(result1.first->first == std::string("0"));
|
||||
CHECK(result1.first->second == 0);
|
||||
CHECK(result1.second == true);
|
||||
|
||||
// Try adding a duplicate (should not construct value, return existing)
|
||||
ETL_OR_STD::pair<Data::iterator, bool> result2 = data.try_emplace(std::string("0"), 99);
|
||||
CHECK(result2.first->first == std::string("0"));
|
||||
CHECK(result2.first->second == 0);
|
||||
CHECK(result2.second == false);
|
||||
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_moved_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
ItemM d1(1);
|
||||
ItemM d2(2);
|
||||
|
||||
data.try_emplace(std::string("1"), etl::move(d1));
|
||||
CHECK(!bool(d1));
|
||||
CHECK(1 == data.at("1").value);
|
||||
|
||||
// Duplicate key: d2 should NOT be moved from
|
||||
data.try_emplace(std::string("1"), etl::move(d2));
|
||||
CHECK(bool(d2));
|
||||
CHECK(1 == data.at("1").value);
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_rvalue_key)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
std::string key1("1");
|
||||
std::string key2("2");
|
||||
std::string key1_dup("1");
|
||||
|
||||
auto result1 = data.try_emplace(etl::move(key1), ItemM(1));
|
||||
CHECK(result1.second == true);
|
||||
CHECK(key1.empty()); // key was moved from
|
||||
CHECK(1 == data.at("1").value);
|
||||
|
||||
auto result2 = data.try_emplace(etl::move(key2), ItemM(2));
|
||||
CHECK(result2.second == true);
|
||||
CHECK(key2.empty()); // key was moved from
|
||||
CHECK(2 == data.at("2").value);
|
||||
|
||||
// Duplicate key: key should NOT be moved from
|
||||
auto result3 = data.try_emplace(etl::move(key1_dup), ItemM(99));
|
||||
CHECK(result3.second == false);
|
||||
CHECK(!key1_dup.empty()); // key was NOT moved
|
||||
CHECK(1 == data.at("1").value);
|
||||
CHECK_EQUAL(2U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range)
|
||||
{
|
||||
|
||||
@ -649,6 +649,40 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::multimap_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
data.emplace(std::string("0"), 0);
|
||||
compare_data.insert(ETL_OR_STD::make_pair(std::string("0"), 0));
|
||||
|
||||
data.emplace(std::string("1"), 1);
|
||||
compare_data.insert(ETL_OR_STD::make_pair(std::string("1"), 1));
|
||||
|
||||
data.emplace(std::string("0"), 2);
|
||||
compare_data.insert(ETL_OR_STD::make_pair(std::string("0"), 2));
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
CHECK(isEqual);
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_moved_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
data.emplace(std::string("1"), ItemM(1));
|
||||
data.emplace(std::string("2"), ItemM(2));
|
||||
data.emplace(std::string("3"), ItemM(3));
|
||||
|
||||
CHECK(1 == data.find("1")->second.value);
|
||||
CHECK(2 == data.find("2")->second.value);
|
||||
CHECK(3 == data.find("3")->second.value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_equal_range)
|
||||
{
|
||||
|
||||
@ -602,6 +602,35 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::multiset_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
data.emplace(0);
|
||||
compare_data.insert(0);
|
||||
|
||||
data.emplace(1);
|
||||
compare_data.insert(1);
|
||||
|
||||
data.emplace(0);
|
||||
compare_data.insert(0);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
CHECK(isEqual);
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.key_comp()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_excess)
|
||||
{
|
||||
Data data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_THROW(data.emplace(99), etl::multiset_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||
{
|
||||
|
||||
@ -399,6 +399,47 @@ namespace
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_DataNDC compare_data;
|
||||
DataNDC data;
|
||||
|
||||
ETL_OR_STD::pair<DataNDC::iterator, bool> result;
|
||||
|
||||
DataNDC::value_type item(0, N0);
|
||||
result = data.emplace(item);
|
||||
compare_data.insert(item);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
CHECK(result.second);
|
||||
CHECK(*result.first == item);
|
||||
|
||||
DataNDC::value_type item2(2, N2);
|
||||
result = data.emplace(item2);
|
||||
compare_data.insert(item2);
|
||||
|
||||
isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
CHECK(result.second);
|
||||
CHECK(*result.first == item2);
|
||||
|
||||
DataNDC::value_type item1(1, N1);
|
||||
result = data.emplace(item1);
|
||||
compare_data.insert(item1);
|
||||
|
||||
isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
CHECK(result.second);
|
||||
CHECK(*result.first == item1);
|
||||
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_changed)
|
||||
{
|
||||
|
||||
@ -262,6 +262,39 @@ namespace
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_DataNDC compare_data;
|
||||
DataNDC data;
|
||||
|
||||
DataNDC::value_type item0(0, N0);
|
||||
data.emplace(item0);
|
||||
compare_data.insert(item0);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
DataNDC::value_type item2(2, N2);
|
||||
data.emplace(item2);
|
||||
compare_data.insert(item2);
|
||||
|
||||
isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
DataNDC::value_type item1(1, N1);
|
||||
data.emplace(item1);
|
||||
compare_data.insert(item1);
|
||||
|
||||
isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_multiple)
|
||||
{
|
||||
|
||||
@ -245,6 +245,36 @@ namespace
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_DataNDC compare_data;
|
||||
DataNDC data;
|
||||
|
||||
data.emplace(N0);
|
||||
compare_data.insert(N0);
|
||||
|
||||
bool isEqual = std::equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
data.emplace(N2);
|
||||
compare_data.insert(N2);
|
||||
|
||||
isEqual = std::equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
data.emplace(N1);
|
||||
compare_data.insert(N1);
|
||||
|
||||
isEqual = std::equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_multiple)
|
||||
{
|
||||
|
||||
@ -278,6 +278,36 @@ namespace
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_DataNDC compare_data;
|
||||
DataNDC data;
|
||||
|
||||
data.emplace(N0);
|
||||
compare_data.insert(N0);
|
||||
|
||||
bool isEqual = std::equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
data.emplace(N2);
|
||||
compare_data.insert(N2);
|
||||
|
||||
isEqual = std::equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
data.emplace(N1);
|
||||
compare_data.insert(N1);
|
||||
|
||||
isEqual = std::equal(data.begin(), data.end(), compare_data.begin());
|
||||
|
||||
CHECK(isEqual);
|
||||
|
||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_value_multiple)
|
||||
{
|
||||
|
||||
@ -558,6 +558,76 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::set_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
Compare_Data compare_data;
|
||||
Data data;
|
||||
|
||||
auto data_result = data.emplace(0);
|
||||
compare_data.insert(0);
|
||||
|
||||
CHECK(data_result.first != data.end());
|
||||
CHECK(*data_result.first == 0);
|
||||
CHECK(data_result.second == true);
|
||||
|
||||
// Duplicate
|
||||
data_result = data.emplace(0);
|
||||
CHECK(*data_result.first == 0);
|
||||
CHECK(data_result.second == false);
|
||||
|
||||
data.emplace(2);
|
||||
compare_data.insert(2);
|
||||
|
||||
data.emplace(1);
|
||||
compare_data.insert(1);
|
||||
|
||||
bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin());
|
||||
CHECK(isEqual);
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.key_comp()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_excess)
|
||||
{
|
||||
Data data(initial_data.begin(), initial_data.end());
|
||||
|
||||
CHECK_THROW(data.emplace(99), etl::set_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_existing_value_when_full)
|
||||
{
|
||||
Data data;
|
||||
ETL_OR_STD::pair<Data::iterator, bool> data_result;
|
||||
|
||||
for (size_t i = 0; i < MAX_SIZE; ++i)
|
||||
{
|
||||
data.emplace(static_cast<int>(i));
|
||||
}
|
||||
|
||||
CHECK(data.full());
|
||||
|
||||
// Emplacing a new key when the set is full should throw etl::set_full.
|
||||
CHECK_THROW(data.emplace(static_cast<int>(MAX_SIZE)), etl::set_full);
|
||||
|
||||
// Emplacing an existing (duplicate) key when the set is full should not
|
||||
// throw; it should return an iterator to the existing element, matching
|
||||
// the behaviour of insert().
|
||||
for (size_t i = 0; i < MAX_SIZE; ++i)
|
||||
{
|
||||
data_result = data.emplace(static_cast<int>(i));
|
||||
|
||||
CHECK(data_result.first != data.end());
|
||||
CHECK_EQUAL(static_cast<int>(i), *data_result.first);
|
||||
CHECK(data_result.second == false);
|
||||
}
|
||||
|
||||
// The set must be unchanged.
|
||||
CHECK_EQUAL(MAX_SIZE, data.size());
|
||||
CHECK_TRUE(std::is_sorted(data.begin(), data.end(), data.key_comp()));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||
{
|
||||
|
||||
@ -768,6 +768,73 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::unordered_map_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
data.emplace(std::string("1"), ItemM(1));
|
||||
data.emplace(std::string("2"), ItemM(2));
|
||||
data.emplace(std::string("3"), ItemM(3));
|
||||
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
CHECK(1 == data.at("1").value);
|
||||
CHECK(2 == data.at("2").value);
|
||||
CHECK(3 == data.at("3").value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_duplicate)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
auto result1 = data.emplace(std::string("1"), ItemM(1));
|
||||
auto result2 = data.emplace(std::string("1"), ItemM(99));
|
||||
|
||||
CHECK(result1.second == true);
|
||||
CHECK(result2.second == false);
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
CHECK(1 == data.at("1").value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
auto result1 = data.try_emplace(std::string("1"), ItemM(1));
|
||||
CHECK(result1.second == true);
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
CHECK(1 == data.at("1").value);
|
||||
|
||||
// Duplicate key: value should NOT be constructed
|
||||
auto result2 = data.try_emplace(std::string("1"), ItemM(99));
|
||||
CHECK(result2.second == false);
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
CHECK(1 == data.at("1").value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_try_emplace_rvalue_key)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
std::string key1("1");
|
||||
std::string key1_dup("1");
|
||||
|
||||
auto result1 = data.try_emplace(etl::move(key1), ItemM(1));
|
||||
CHECK(result1.second == true);
|
||||
CHECK(key1.empty()); // key was moved from
|
||||
CHECK(1 == data.at("1").value);
|
||||
|
||||
// Duplicate key: key should NOT be moved from
|
||||
auto result2 = data.try_emplace(etl::move(key1_dup), ItemM(99));
|
||||
CHECK(result2.second == false);
|
||||
CHECK(!key1_dup.empty()); // key was NOT moved
|
||||
CHECK(1 == data.at("1").value);
|
||||
CHECK_EQUAL(1U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||
{
|
||||
|
||||
@ -565,6 +565,20 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::unordered_multimap_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
data.emplace(std::string("1"), ItemM(1));
|
||||
data.emplace(std::string("2"), ItemM(2));
|
||||
data.emplace(std::string("3"), ItemM(3));
|
||||
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
CHECK(2 == data.find("2")->second.value);
|
||||
CHECK(3 == data.find("3")->second.value);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||
{
|
||||
|
||||
@ -563,6 +563,21 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::unordered_multiset_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
auto result1 = data.emplace(ItemM(1));
|
||||
auto result2 = data.emplace(ItemM(2));
|
||||
auto result3 = data.emplace(ItemM(1));
|
||||
|
||||
CHECK(result1 != data.end());
|
||||
CHECK(result2 != data.end());
|
||||
CHECK(result3 != data.end());
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||
{
|
||||
|
||||
@ -159,6 +159,7 @@ namespace
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
#include "etl/private/diagnostic_null_dereference_push.h"
|
||||
SUITE(test_unordered_set)
|
||||
{
|
||||
static const size_t SIZE = 10;
|
||||
@ -544,6 +545,21 @@ namespace
|
||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::unordered_set_full);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_value)
|
||||
{
|
||||
DataM data;
|
||||
|
||||
auto result1 = data.emplace(ItemM(1));
|
||||
auto result2 = data.emplace(ItemM(2));
|
||||
auto result3 = data.emplace(ItemM(3));
|
||||
|
||||
CHECK(result1.second == true);
|
||||
CHECK(result2.second == true);
|
||||
CHECK(result3.second == true);
|
||||
CHECK_EQUAL(3U, data.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||
{
|
||||
@ -599,6 +615,46 @@ namespace
|
||||
CHECK(data.size() == SIZE);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_emplace_existing_value_when_full)
|
||||
{
|
||||
DataNDC data;
|
||||
|
||||
data.insert(N0); // Inserted
|
||||
data.insert(N1); // Inserted
|
||||
data.insert(N2); // Inserted
|
||||
data.insert(N3); // Inserted
|
||||
data.insert(N4); // Inserted
|
||||
data.insert(N5); // Inserted
|
||||
data.insert(N6); // Inserted
|
||||
data.insert(N7); // Inserted
|
||||
data.insert(N8); // Inserted
|
||||
data.insert(N9); // Inserted
|
||||
|
||||
CHECK(data.full());
|
||||
|
||||
// Emplacing a new key when the unordered_set is full should throw.
|
||||
CHECK_THROW(data.emplace(N10), etl::unordered_set_full);
|
||||
|
||||
// Emplacing an existing (duplicate) key when the unordered_set is full
|
||||
// should not throw; it should return an iterator to the existing element,
|
||||
// matching the behaviour of insert().
|
||||
ETL_OR_STD::pair<DataNDC::iterator, bool> result;
|
||||
|
||||
CHECK_NO_THROW(result = data.emplace(N0));
|
||||
CHECK(result.first != data.end());
|
||||
CHECK(*result.first == N0);
|
||||
CHECK(result.second == false);
|
||||
|
||||
CHECK_NO_THROW(result = data.emplace(N9));
|
||||
CHECK(result.first != data.end());
|
||||
CHECK(*result.first == N9);
|
||||
CHECK(result.second == false);
|
||||
|
||||
// The unordered_set must be unchanged.
|
||||
CHECK(data.size() == SIZE);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||
{
|
||||
@ -1067,4 +1123,5 @@ namespace
|
||||
CHECK_FALSE(data.contains(not_inserted));
|
||||
}
|
||||
}
|
||||
#include "etl/private/diagnostic_pop.h"
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user