mirror of
https://github.com/ETLCPP/etl.git
synced 2026-07-30 16:26:17 +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;
|
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
|
#endif
|
||||||
|
|
||||||
//*********************************************************************
|
//*********************************************************************
|
||||||
|
|||||||
@ -339,7 +339,23 @@ namespace etl
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
ETL_OR_STD::pair<iterator, bool> emplace(Args&&... 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;
|
ETL_OR_STD::pair<iterator, bool> result;
|
||||||
|
|
||||||
@ -360,7 +376,7 @@ namespace etl
|
|||||||
// Destroy it.
|
// Destroy it.
|
||||||
pvalue->~value_type();
|
pvalue->~value_type();
|
||||||
storage.release(pvalue);
|
storage.release(pvalue);
|
||||||
result = ETL_OR_STD::pair<iterator, bool>(end(), false);
|
result = ETL_OR_STD::pair<iterator, bool>(i_element, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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
|
/// Returns an iterator pointing to the first element in the container
|
||||||
/// whose key is not considered to go before the key provided or end()
|
/// whose key is not considered to go before the key provided or end()
|
||||||
@ -1545,6 +1727,106 @@ namespace etl
|
|||||||
return *node;
|
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
|
#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
|
/// Returns an iterator pointing to the first element in the container
|
||||||
/// whose key is not considered to go before the key provided or end()
|
/// whose key is not considered to go before the key provided or end()
|
||||||
@ -1567,6 +1596,21 @@ namespace etl
|
|||||||
ETL_INCREMENT_DEBUG_COUNT;
|
ETL_INCREMENT_DEBUG_COUNT;
|
||||||
return *node;
|
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
|
#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
|
/// Returns an iterator pointing to the first element in the container
|
||||||
/// whose key is not considered to go before the key provided or end()
|
/// 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);
|
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.
|
/// Inserts a value to the reference_flat_map.
|
||||||
/// If asserts or exceptions are enabled, emits flat_map_full if the
|
/// If asserts or exceptions are enabled, emits flat_map_full if the
|
||||||
|
|||||||
@ -485,6 +485,18 @@ namespace etl
|
|||||||
return insert_at(i_element, value);
|
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.
|
/// Inserts a value to the flat_multi.
|
||||||
/// If asserts or exceptions are enabled, emits flat_map_full if the
|
/// If asserts or exceptions are enabled, emits flat_map_full if the
|
||||||
|
|||||||
@ -478,6 +478,18 @@ namespace etl
|
|||||||
return result;
|
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.
|
/// Inserts a value to the reference_flat_multiset.
|
||||||
/// If asserts or exceptions are enabled, emits reference_flat_multiset_full
|
/// If asserts or exceptions are enabled, emits reference_flat_multiset_full
|
||||||
|
|||||||
@ -455,6 +455,18 @@ namespace etl
|
|||||||
return insert_at(i_element, value);
|
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.
|
/// Inserts a value to the reference_flat_set.
|
||||||
/// If asserts or exceptions are enabled, emits reference_flat_set_full if
|
/// 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
|
/// Returns an iterator pointing to the first element in the container
|
||||||
/// whose key is not considered to go before the key provided or end()
|
/// 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.
|
/// Erases an element.
|
||||||
///\param key The key to erase.
|
///\param key The key to erase.
|
||||||
|
|||||||
@ -687,10 +687,10 @@ namespace etl
|
|||||||
//*********************************************************************
|
//*********************************************************************
|
||||||
iterator insert(const_reference key_value_pair)
|
iterator insert(const_reference key_value_pair)
|
||||||
{
|
{
|
||||||
iterator result = end();
|
|
||||||
|
|
||||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
||||||
|
|
||||||
|
iterator result = end();
|
||||||
|
|
||||||
const_key_reference key = key_value_pair.first;
|
const_key_reference key = key_value_pair.first;
|
||||||
|
|
||||||
// Get the hash index.
|
// Get the hash index.
|
||||||
@ -759,10 +759,10 @@ namespace etl
|
|||||||
//*********************************************************************
|
//*********************************************************************
|
||||||
iterator insert(rvalue_reference key_value_pair)
|
iterator insert(rvalue_reference key_value_pair)
|
||||||
{
|
{
|
||||||
iterator result = end();
|
|
||||||
|
|
||||||
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
ETL_ASSERT(!full(), ETL_ERROR(unordered_multimap_full));
|
||||||
|
|
||||||
|
iterator result = end();
|
||||||
|
|
||||||
const_key_reference key = key_value_pair.first;
|
const_key_reference key = key_value_pair.first;
|
||||||
|
|
||||||
// Get the hash index.
|
// 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.
|
/// Erases an element.
|
||||||
///\param key The key to erase.
|
///\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.
|
/// Erases an element.
|
||||||
///\param key The key to erase.
|
///\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.
|
/// Erases an element.
|
||||||
///\param key The key to erase.
|
///\param key The key to erase.
|
||||||
|
|||||||
@ -981,6 +981,66 @@ namespace
|
|||||||
CHECK(!result.second);
|
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)
|
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -709,6 +709,21 @@ namespace
|
|||||||
CHECK(isEqual);
|
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)
|
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -728,6 +728,14 @@ namespace
|
|||||||
CHECK(isEqual);
|
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)
|
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -754,6 +754,47 @@ namespace
|
|||||||
CHECK_EQUAL(compare.size(), data.size());
|
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)
|
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -808,6 +808,166 @@ namespace
|
|||||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::map_full);
|
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)
|
TEST_FIXTURE(SetupFixture, test_equal_range)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -649,6 +649,40 @@ namespace
|
|||||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::multimap_full);
|
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)
|
TEST_FIXTURE(SetupFixture, test_equal_range)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -602,6 +602,35 @@ namespace
|
|||||||
CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::multiset_full);
|
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)
|
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -399,6 +399,47 @@ namespace
|
|||||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
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)
|
TEST_FIXTURE(SetupFixture, test_insert_value_changed)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -262,6 +262,39 @@ namespace
|
|||||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
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)
|
TEST_FIXTURE(SetupFixture, test_insert_value_multiple)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -245,6 +245,36 @@ namespace
|
|||||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
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)
|
TEST_FIXTURE(SetupFixture, test_insert_value_multiple)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -278,6 +278,36 @@ namespace
|
|||||||
CHECK(std::is_sorted(data.begin(), data.end()));
|
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)
|
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);
|
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)
|
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);
|
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)
|
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);
|
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)
|
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);
|
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)
|
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -159,6 +159,7 @@ namespace
|
|||||||
};
|
};
|
||||||
|
|
||||||
//***************************************************************************
|
//***************************************************************************
|
||||||
|
#include "etl/private/diagnostic_null_dereference_push.h"
|
||||||
SUITE(test_unordered_set)
|
SUITE(test_unordered_set)
|
||||||
{
|
{
|
||||||
static const size_t SIZE = 10;
|
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);
|
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)
|
TEST_FIXTURE(SetupFixture, test_insert_moved_value)
|
||||||
{
|
{
|
||||||
@ -599,6 +615,46 @@ namespace
|
|||||||
CHECK(data.size() == SIZE);
|
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)
|
TEST_FIXTURE(SetupFixture, test_erase_key)
|
||||||
{
|
{
|
||||||
@ -1067,4 +1123,5 @@ namespace
|
|||||||
CHECK_FALSE(data.contains(not_inserted));
|
CHECK_FALSE(data.contains(not_inserted));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#include "etl/private/diagnostic_pop.h"
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user