Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/named req/AssociativeContainer"

From cppreference.com
< cpp‎ | named req
(Added LWG issue #354 DR.)
m (Member functions and operators: add bounding rectangle and scroll-bars to the table.)
 
(13 intermediate revisions by 4 users not shown)
Line 3: Line 3:
  
 
An {{named req|AssociativeContainer}} is an ordered {{named req|Container}} that provides fast lookup of objects based on keys.
 
An {{named req|AssociativeContainer}} is an ordered {{named req|Container}} that provides fast lookup of objects based on keys.
 +
 +
An associative container supports ''unique keys'' if it may contain at most one element for each key. Otherwise, it supports ''equivalent keys''.
  
 
===Requirements===
 
===Requirements===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc h1|Legend}}
+
{{dsc h2|Legend}}
{{dsc|{{ttb|X}}|Container type}}
+
{{dsc|{{tt|X}}|An associative container class}}
{{dsc|{{ttb|a}}|Value of type {{ttb|X}}}}
+
{{dsc|{{tt|T}}|The element type of {{tt|X}}}}
{{dsc|{{ttb|a2}}|Value of a type {{ttb|Y}} whose [[cpp/container/node handle|node handles]] are compatible with X}}
+
{{dsc|{{tt|A}}|The allocator type of {{tt|X}}: {{tt|X::allocator_type}} if it exists, otherwise {{c/core|std::allocator<X::value_type>}}}}
{{dsc|{{ttb|b}}|Possibly const value of type {{ttb|X}}}}
+
{{dsc|{{c|a}}|A value of type {{tt|X}}}}
{{dsc|{{ttb|u}}|Arbitrary variable name}}
+
{{dsc|{{c|a2}}|A value of a type {{tt|Y}} whose [[cpp/container/node handle|node handles]] are compatible with {{tt|X}}}}
{{dsc|{{ttb|a_uniq}}|Value of type {{ttb|X}} when {{ttb|X}} supports unique keys}}
+
{{dsc|{{c|b}}|A value of type {{tt|X}} or {{c/core|const X}}}}
{{dsc|{{ttb|a_eq}}|Value of type {{ttb|X}} when {{ttb|X}} supports multiple keys}}
+
{{dsc|{{c|u}}|A name of a variable beging declared}}
{{dsc|{{ttb|a_tran}}|Possibly const value of type {{ttb|X}} when type {{tt|X::key_compare::is_transparent}} exists}}
+
{{dsc|{{c|a_uniq}}|A value of type {{tt|X}} when {{tt|X}} supports unique keys}}
{{dsc|{{ttb|i}}, {{ttb|j}}|{{named req|InputIterator}}s denoting a valid range and referring to elements implicitly convertible to {{tt|X::value_type}}}}
+
{{dsc|{{c|a_eq}}|A value of type {{tt|X}} when {{tt|X}} supports equivalent keys}}
{{dsc|{{ttb|p}}|A valid const iterator to {{ttb|a}} }}
+
{{dsc|{{c|a_tran}}|A value of type {{tt|X}} or {{c/core|const X}} when type {{tt|X::key_compare::is_transparent}} exists}}
{{dsc|{{ttb|q}}|A valid dereferenceable const iterator to {{ttb|a}} }}
+
{{dsc|{{c|i}}, {{c|j}}|The {{named req|InputIterator}}s referring to elements implicitly convertible to {{tt|X::value_type}}}}
{{dsc|{{ttb|r}}|A valid dereferenceable iterator to {{ttb|a}} }}
+
{{dsc|{{range|i|j}}|A valid range}}
{{dsc|{{ttb|q1}}, {{ttb|q2}}|const iterators denoting a valid range in {{ttb|a}} }}
+
{{dsc|{{c|rg}}<br>{{mark since c++23}}|A value of a type {{tt|R}} that models {{lti|cpp/ranges/to#container compatible range|container-compatible-range}}{{tt|<value_type>}}}}
{{dsc|{{ttb|il}}|An object of type {{lc|std::initializer_list}}<value_type>}}
+
{{dsc|{{c|p}}|A valid constant iterator to {{c|a}}}}
{{dsc|{{ttb|t}}|A value of type {{ttb|X::value_type}} }}
+
{{dsc|{{c|q}}|A valid dereferenceable constant iterator to {{c|a}}}}
{{dsc|{{ttb|k}}|A value of type {{ttb|X::key_type}} }}
+
{{dsc|{{c|r}}|A valid dereferenceable iterator to {{c|a}}}}
{{dsc|{{ttb|c}}|A possibly const value of type {{ttb|X::key_compare}} }}
+
{{dsc|{{c|q1}}, {{c|q2}}|A valid range of const iterators in {{c|a}}}}
{{dsc|{{ttb|kl}}|A value such that {{ttb|a}} is partitioned with respect to {{c|c(r, kl)}}, with {{tt|r}} the key value of {{tt|e}} and {{tt|e}} in {{tt|a}}}}
+
{{dsc|{{c|il}}|An object of type {{c/core|std::initializer_list<X::value_type>}}}}
{{dsc|{{ttb|ku}}|A value such that {{ttb|a}} is partitioned with respect to {{c|!c(ku, r)}}}}
+
{{dsc|{{c|t}}|A value of type {{tt|X::value_type}}}}
{{dsc|{{ttb|ke}}|A value such that {{ttb|a}} is partitioned with respect to {{c|c(r, ke)}} and {{c|!c(ke, r)}}, with {{c|c(r, ke)}} implying {{c|!c(ke, r)}}}}
+
{{dsc|{{c|k}}|A value of type {{tt|X::key_type}}}}
{{dsc|{{ttb|A}}|Storage allocator used by {{ttb|X}}, or {{lc|std::allocator_type<X::value_type>}} }}
+
{{dsc|{{c|c}}|A value of type {{tt|X::key_compare}} or {{c/core|const X::key_compare}}}}
{{dsc|{{ttb|m}}|Allocator of a type convertible to {{ttb|A}} }}
+
{{dsc|{{c|kl}}|A value such that {{c|a}} is partitioned with respect to {{c|c(x, kl)}}, with {{c|x}} the key value of {{c|e}} and {{c|e}} in {{c|a}}}}
{{dsc|{{ttb|nh}}|A non-const rvalue of type {{tt|X::node_type}} }}
+
{{dsc|{{c|ku}}|A value such that {{c|a}} is partitioned with respect to {{c|!c(ku, x)}}, with {{c|x}} the key value of {{c|e}} and {{c|e}} in {{c|a}}}}
 +
{{dsc|{{c|ke}}|A value such that {{c|a}} is partitioned with respect to {{c|c(x, ke)}} and {{c|!c(ke, x)}}, with {{c|c(x, ke)}} implying {{c|!c(ke, x)}} and with {{c|x}} the key value of {{c|e}} and {{c|e}} in {{c|a}}}}
 +
{{dsc|{{c|kx}}<br>{{mark since c++23}}|A value such that:
 +
* {{c|a}} is partitioned with respect to {{c|c(x, kx)}} and {{c|!c(kx, x)}}, with {{c|c(x, kx)}} implying {{c|!c(kx, x)}} and with {{c|x}} the key value of {{c|e}} and {{c|e}} in {{c|a}}, and
 +
* {{c|kx}} is not convertible to either {{tt|X::iterator}} or {{tt|X::const_iterator}}}}
 +
{{dsc|{{c|m}}|An allocator of a type convertible to {{tt|A}}}}
 +
{{dsc|{{c|nh}}|A non-const rvalue of type {{tt|X::node_type}}}}<!--NB: 'nh' is used in the table below (see N4950, e.g., § 24.2.7.1-84, p.893); it was accidentally dropped out of N4950 (C++23 final draft), but present in IS-C++20 text and should be restored in IS-C++23!-->
 
{{dsc end}}
 
{{dsc end}}
  
{|class=wikitable
+
The type {{tt|X}} satisfies {{named req/core|AssociativeContainer}} if
!expression||return type||pre/requirements||post/effects||complexity
+
* The type {{tt|X}} satisfies {{rev inl|until=c++11|{{named req|Container}}}}{{rev inl|since=c++11|{{named req|AllocatorAwareContainer}}}},
 +
* Is parameterized on {{tt|Key}} and an ordering relation {{tt|Compare}} that induces a {{rlp|Compare|strict weak ordering}} on elements of {{tt|Key}}, and
 +
** In addition, {{lc|std::map}} and {{lc|std::multimap}} associate an arbitrary ''mapped type'' {{tt|T}} with the {{tt|Key}}.
 +
** The object of type {{tt|Compare}} is called the ''comparison object'' of a container of type {{tt|X}}.
 +
* The following expressions must be valid and have their specified effects for all associative containers:
 +
 
 +
====Types====
 +
{|class=wikitable
 +
!Name||Type||Requirements
 
|-
 
|-
|{{c|X::key_type}}||{{ttb|Key}}||{{ttb|Key}} is {{named req|Destructible}}|| ||compile time
+
|{{tt|key_type}}
 +
|{{tt|Key}}
 +
|
 
|-
 
|-
|{{c|X::key_compare}}||{{ttb|Compare}}|| || ||compile time
+
|{{tt|mapped_type}}
 +
|{{tt|T}} (for {{lc|std::map}} and {{lc|std::multimap}} only)
 +
|
 
|-
 
|-
|{{c|X::value_compare}}||a type satisfying {{named req|BinaryPredicate}}||{{c|key_compare}} for {{c|std::set}} and {{c|std::multiset}}; an ordering relation over {{ttb|Key}} for {{c|std::map}} and {{c|std::multimap}} || ||compile time
+
|{{tt|value_type}}
 +
|
 +
*{{tt|Key}} (for {{lc|std::set}} and {{lc|std::multiset}} only)
 +
* {{c/core|std::pair<const Key, T>}}(for {{lc|std::map}} and {{lc|std::multimap}} only)
 +
 
 +
|{{named req|Erasable}} from {{tt|X}}
 
|-
 
|-
|{{c|X(c)}}, {{c|X a(c);}}|| ||{{c|key_compare}} is {{named req|CopyConstructible}}||Construct an empty container using a copy of {{c|c}} as {{ttb|key_comp}}||constant
+
|{{tt|key_compare}}
 +
|{{tt|Compare}}
 +
|{{named req|CopyConstructible}}
 
|-
 
|-
|{{c|X()}}, {{c|X a;}}|| ||{{c|key_compare}} is {{named req|DefaultConstructible}}||Construct an empty container using a {{c|Compare()}} as {{ttb|key_comp}}||constant
+
|{{tt|value_compare}}
 +
|
 +
* same as {{tt|key_compare}} (for {{lc|std::set}} and {{lc|std::multiset}})
 +
* an ordering relation on pairs induced by the first component (i.e. {{tt|Key}}) (for {{lc|std::map}} and {{lc|std::multimap}})
 +
 
 +
|{{named req|BinaryPredicate}}
 
|-
 
|-
|{{c|X(i, j, c)}}, {{c|X a(i, j, c);}}|| ||{{c|key_compare}} is {{named req|CopyConstructible}} and {{c|value_type}} is {{named req|EmplaceConstructible}} into {{c|X}} from {{c|*i}}||Constructs an empty container using a copy of {{c|c}} as {{ttb|key_comp}} and inserts all elements from the range {{tt|[i; j)}}||generally {{tt|N log N}}, or {{tt|N}} if {{tt|[i, j)}} is sorted (where {{tt|N}} is {{c|std::distance(i, j)}})
+
|{{tt|node_type}}
 +
|A specialization of the [[cpp/container/node handle|node-handle class template]], such that the public nested types are the same types as the corresponding types in {{tt|X}}.
 +
|
 +
|}
 +
 
 +
====Member functions and operators====
 +
<div style="max-width: 100%; max-height: 90vh; overflow: scroll;">
 +
{|class=wikitable style="font-size:0.9em"
 +
!Expression||Result||Preconditions||Effects||Returns||Complexity
 
|-
 
|-
|{{c|X(i, j)}}, {{c|X a(i, j);}}|| ||{{c|key_compare}} is {{named req|DefaultConstructible}} and {{c|value_type}} is {{named req|EmplaceConstructible}} into {{c|X}} from {{c|*i}}||Constructs an empty container using a {{c|Compare()}} as {{ttb|key_comp}} and inserts all elements from the range {{tt|[i; j)}}||generally {{tt|N log N}}, or {{tt|N}} if {{tt|[i, j)}} is sorted according to {{c|value_comp()}} (where {{tt|N}} is {{c|std::distance(i, j)}})
+
|{{c|X(c)}}
 +
|
 +
|
 +
|Constructs an empty container. Uses a copy of {{c|c}} as a comparison object
 +
|
 +
|Constant
 
|-
 
|-
|{{c|X(il);}}|| ||Equivalent to {{c|X(il.begin(), il.end());}}||Equivalent to {{c|X(il.begin(), il.end());}}
+
|{{c|1=X u = X();}}<br>{{c|X u;}}
 +
|
 +
|{{tt|key_compare}} meets the {{named req|DefaultConstructible}} requirements
 +
|Constructs an empty container. Uses {{c|Compare()}} as a comparison object
 +
|
 +
|Constant
 
|-
 
|-
|{{c|a {{=}} il}}||{{c|X&}}||{{ttb|T}} is {{named req|CopyInsertable}} into {{ttb|X}} and also {{named req|CopyAssignable}}||Assign the range {{c|[il.begin(), il.end())}} into {{ttb|a}}. Elements of {{ttb|a}} that were not assigned to are destroyed||generally {{tt|N log N}}, or {{tt|N}} if {{c|[il.begin(), il.end())}} is sorted according to {{c|value_comp()}} (where {{tt|N}} is {{c|il.size() + a.size()}})
+
|{{c|X(i, j, c)}}
 +
|
 +
|{{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|*i}}
 +
|Constructs an empty container and inserts elements from the range {{range|i|j}} into it; uses {{c|c}} as a comparison object
 +
|
 +
|rowspan="2"|{{c|N·log(N)}} in general, where {{tt|N}} has the value {{c|std::distance(i, j)}}; linear if {{range|i|j}} is sorted with respect to {{c|value_comp()}}
 
|-
 
|-
|{{c|a.key_comp()}}||{{c|X::key_compare}}|| ||The comparison object with which {{ttb|a}} was constructed is returned.||constant
+
|{{c|X(i, j)}}
 +
|
 +
|{{tt|key_compare}} meets the {{named req|DefaultConstructible}} requirements. {{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|*i}}
 +
|Constructs an empty container and inserts elements from the range {{range|i|j}} into it; uses {{c|Compare()}} as a comparison object
 +
|
 +
<!--|{{c|N·log(N)}} in general, where {{tt|N}} has the value {{c|std::distance(i, j)}}; linear if {{range|i|j}} is sorted with respect to {{c|value_comp()}}-->
 
|-
 
|-
|{{c|a.value_comp()}}||{{c|X::value_compare}}|| ||An object of type {{c|X::value_compare}} constructed out of the comparison object is returned.||constant
+
|{{c|X(from_range, rg, c)}}<br>{{mark since c++23}}
 +
|
 +
|{{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|*ranges::begin(rg)}}
 +
|Constructs an empty container and inserts each element from {{c|rg}} into it. Uses {{c|c}} as the comparison object
 +
|
 +
|rowspan="2"|{{c|N·log(N)}} in general, where {{tt|N}} has the value {{c|ranges::distance(rg)}}; linear if {{c|rg}} is sorted with respect to {{c|value_comp()}}
 +
|-
 +
|{{c|X(from_range, rg)}}<br>{{mark since c++23}}
 +
|
 +
|{{tt|key_compare}} meets the {{named req|DefaultConstructible}} requirements. {{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|*ranges::begin(rg)}}
 +
|Constructs an empty container and inserts each element from {{c|rg}} into it. Uses {{c|Compare()}} as the comparison object
 +
|
 +
<!--|Same as {{c|X(std::from_range, rg, c)}}-->
 +
|-
 +
|{{c|X(il, c)}}
 +
|
 +
|
 +
|{{c|X(il.begin(), il.end(), c)}}
 +
|
 +
|
 +
|-
 +
|{{c|X(il)}}
 +
|
 +
|
 +
|{{c|X(il.begin(), il.end())}}
 +
|
 +
|
 +
|-
 +
|{{c|1=a = il}}
 +
|{{c|X&}}
 +
|{{tt|value_type}} is {{named req|CopyInsertable}} into {{tt|X}} and {{named req|CopyAssignable}}
 +
|Assigns the range {{range|il.begin()|il.end()}} into {{c|a}}. All existing elements of {{c|a}} are either assigned to or destroyed
 +
|
 +
|{{c|N·log(N)}} in general, where {{tt|N}} has the value {{c|il.size() + a.size()}}; linear if {{range|il.begin()|il.end()}} is sorted with respect to {{c|value_comp()}}
 +
|-
 +
|{{c|b.key_comp()}}
 +
|{{tt|X::key_compare}}
 +
|
 +
|
 +
|The comparison object out of which {{c|b}} was constructed
 +
|Constant
 +
|-
 +
|{{c|b.value_comp()}}
 +
|{{tt|X::value_compare}}
 +
|
 +
|
 +
|An object of {{tt|value_compare}} constructed out of the comparison object
 +
|Constant
 +
|-
 +
|{{c|a_uniq.emplace(args)}}
 +
|{{c multi
 +
|std::pair<
 +
|  iterator,
 +
|  bool>
 +
}}
 +
|{{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|args}}
 +
|Inserts a {{tt|value_type}} object {{c|t}} constructed with {{c|std::forward<Args>(args)...}} if and only if there is no element in the container with key equivalent to the key of {{c|t}}
 +
|The {{c|bool}} component of the returned pair is {{c|true}} if and only if the insertion takes place, and the iterator component of the pair points to the element with key equivalent to the key of {{c|t}}
 +
|Logarithmic
 +
|-
 +
|{{c|a_eq.emplace(args)}}
 +
|{{tt|iterator}}
 +
|{{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|args}}
 +
|Inserts a {{tt|value_type}} object {{c|t}} constructed with {{c|std::forward<Args>(args)...}}. If a range containing elements equivalent to {{c|t}} exists in {{c|a_eq}}, {{c|t}} is inserted at the end of that range
 +
|An iterator pointing to the newly inserted element
 +
|Logarithmic
 +
|-
 +
|{{c|a.emplace_hint(p, args)}}
 +
|{{tt|iterator}}
 +
|
 +
|Equivalent to
 +
{{c multi
 +
|a.emplace(
 +
|  std::forward<Args>(args)...)
 +
}},
 +
except that the element is inserted as close as possible to the position just prior to {{c|p}}
 +
|An iterator pointing to the element with the key equivalent to the newly inserted element
 +
|Logarithmic in general, but amortized constant if the element is inserted right before {{c|p}}
 +
|-
 +
|{{c|a_uniq.insert(t)}}
 +
|{{c multi
 +
|std::pair<
 +
|  iterator,
 +
|  bool>
 +
}}
 +
|If {{c|t}} is a non-const rvalue, {{tt|value_type}} is {{named req|MoveInsertable}} into {{tt|X}}; otherwise, {{tt|value_type}} is {{named req|CopyInsertable}} into {{tt|X}}
 +
|Inserts {{c|t}} if and only if there is no element in the container with key equivalent to the key of {{c|t}}
 +
|The {{c|bool}} component of the returned pair is {{c|true}} if and only if the insertion takes place, and the {{tt|iterator}} component of the pair points to the element with key equivalent to the key of {{c|t}}
 +
|Logarithmic
 +
|-
 +
|{{c|a_eq.insert(t)}}
 +
|{{tt|iterator}}
 +
|If {{c|t}} is a non-const rvalue, {{tt|value_type}} is {{named req|MoveInsertable}} into {{tt|X}}; otherwise, {{tt|value_type}} is {{named req|CopyInsertable}} into {{tt|X}}
 +
|Inserts {{c|t}} and returns the iterator pointing to the newly inserted element. If a range containing elements equivalent to {{c|t}} exists in {{c|a_eq}}, {{c|t}} is inserted at the end of that range
 +
|
 +
|Logarithmic
 +
|-
 +
|{{c|a.insert(p, t)}}
 +
|{{tt|iterator}}
 +
|If {{c|t}} is a non-const rvalue, {{tt|value_type}} is {{named req|MoveInsertable}} into {{tt|X}}; otherwise, {{tt|value_type}} is {{named req|CopyInsertable}} into {{tt|X}}
 +
|Inserts {{c|t}} if and only if there is no element with key equivalent to the key of {{c|t}} in containers with unique keys; always inserts {{c|t}} in containers with equivalent keys. {{c|t}} is inserted as close as possible to the position just prior to {{c|p}}
 +
|An iterator pointing to the element with key equivalent to the key of {{c|t}}
 +
|Logarithmic in general, but amortized constant if {{c|t}} is inserted right before {{c|p}}
 +
|-
 +
|{{c|a.insert(i, j)}}
 +
|{{c|void}}
 +
|{{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|*i}}. Neither {{c|i}} nor {{c|j}} are iterators into {{c|a}}
 +
|Inserts each element from the range {{range|i|j}} if and only if there is no element with key equivalent to the key of that element in containers with unique keys; always inserts that element in containers with equivalent keys
 +
|
 +
|{{c|N·log(a.size() + N)}}, where {{tt|N}} has the value {{c|std::distance(i, j)}}
 +
|-
 +
|{{c|a.insert_range(rg)}}<br>{{mark since c++23}}
 +
|{{c|void}}
 +
|{{tt|value_type}} is {{named req|EmplaceConstructible}} into {{tt|X}} from {{c|*ranges::begin(rg)}}. {{c|rg}} and {{c|a}} do not overlap
 +
|Inserts each element from {{c|rg}} if and only if there is no element with key equivalent to the key of that element in containers with unique keys; always inserts that element in containers with equivalent keys
 +
|
 +
|{{c|N·log(a.size() + N)}}, where {{tt|N}} has the value {{c|ranges::distance(rg)}}
 +
|-
 +
|{{c|a.insert(il)}}
 +
|
 +
|
 +
|{{c|a.insert(il.begin(), il.end())}}
 +
|
 +
|
 +
|-
 +
|{{c|a_uniq.insert(nh)}}
 +
|{{tt|insert_return_type}}
 +
|{{c|nh}} is empty or
 +
{{c multi
 +
|a_uniq.get_allocator()
 +
|{{==}}
 +
|nh.get_allocator()
 +
}}
 +
is {{c|true}}
 +
|If {{c|nh}} is empty, has no effect. Otherwise, inserts the element owned by {{c|nh}} if and only if there is no element in the container with a key equivalent to {{c|nh.key()}}
 +
|If {{c|nh}} is empty, {{tt|inserted}} is {{c|false}}, {{tt|position}} is {{c|end()}}, and {{tt|node}} is empty. Otherwise if the insertion took place, {{tt|inserted}} is {{c|true}}, {{tt|position}} points to the inserted element, and {{tt|node}} is empty; if the insertion failed, {{tt|inserted}} is {{c|false}}, {{tt|node}} has the previous value of {{c|nh}}, and {{tt|position}} points to an element with a key equivalent to {{c|nh.key()}}
 +
|Logarithmic
 +
|-
 +
|{{c|a_eq.insert(nh)}}
 +
|{{tt|iterator}}
 +
|{{c|nh}} is empty or
 +
{{c multi
 +
|a_eq.get_allocator()
 +
|{{==}}
 +
|nh.get_allocator()
 +
}}
 +
is {{c|true}}
 +
|If {{c|nh}} is empty, has no effect and returns {{c|a_eq.end()}}. Otherwise, inserts the element owned by {{c|nh}} and returns an iterator pointing to the newly inserted element. If a range containing elements with keys equivalent to {{c|nh.key()}} exists in {{c|a_eq}}, the element is inserted at the end of that range. Ensures: {{c|nh}} is empty
 +
|
 +
|Logarithmic
 +
|-
 +
|{{c|a.insert(p, nh)}}
 +
|{{tt|iterator}}
 +
|{{c|nh}} is empty or
 +
{{c multi
 +
|a.get_allocator()
 +
|{{==}}
 +
|nh.get_allocator()
 +
}}
 +
is {{c|true}}
 +
|If {{c|nh}} is empty, has no effect and returns {{c|a.end()}}. Otherwise, inserts the element owned by {{c|nh}} if and only if there is no element with key equivalent to {{c|nh.key()}} in containers with unique keys; always inserts the element owned by {{c|nh}} in containers with equivalent keys. The element is inserted as close as possible to the position just prior to {{c|p}}. Ensures: {{c|nh}} is empty if insertion succeeds, unchanged if insertion fails
 +
|An iterator pointing to the element with key equivalent to {{c|nh.key()}}
 +
|Logarithmic in general, but amortized constant if the element is inserted right before {{c|p}}
 +
|-
 +
|{{c|a.extract(k)}}
 +
|{{tt|node_type}}
 +
|
 +
|Removes the first element in the container with key equivalent to {{c|k}}
 +
|A {{tt|node_type}} owning the element if found, otherwise an empty {{tt|node_type}}
 +
|{{c|log(a.size())}}
 +
|-
 +
|{{c|a_tran.extract(kx)}}<br>{{mark since c++23}}
 +
|{{tt|node_type}}
 +
|
 +
|Removes the first element in the container with key {{c|r}} such that {{c|!c(r, kx) && !c(kx, r)}} is {{c|true}}
 +
|A {{tt|node_type}} owning the element if found, otherwise an empty {{tt|node_type}}
 +
|{{c|log(a_tran.size())}}
 +
|-
 +
|{{c|a.extract(q)}}
 +
|{{tt|node_type}}
 +
|
 +
|Removes the element pointed to by {{c|q}}
 +
|A {{tt|node_type}} owning that element
 +
|Amortized constant
 +
|-
 +
|{{c|a.merge(a2)}}
 +
|{{c|void}}
 +
|{{c multi
 +
|a.get_allocator()
 +
|{{==}}
 +
|a2.get_allocator()
 +
}}
 +
|Attempts to extract each element in {{c|a2}} and insert it into {{c|a}} using the comparison object of {{c|a}}. In containers with unique keys, if there is an element in {{c|a}} with key equivalent to the key of an element from {{c|a2}}, then that element is not extracted from {{c|a2}}. Ensures: Pointers and references to the transferred elements of {{c|a2}} refer to those same elements but as members of {{c|a}}. Iterators referring to the transferred elements will continue to refer to their elements, but they now behave as iterators into {{c|a}}, not into {{c|a2}}. Throws: Nothing unless the comparison object throws
 +
|
 +
|{{c|N·log(a.size() + N)}}, where {{tt|N}} has the value {{c|a2.size()}}
 +
|-
 +
|{{c|a.erase(k)}}
 +
|{{tt|size_type}}
 +
|
 +
|Erases all elements in the container with key equivalent to {{c|k}}
 +
|The number of erased elements
 +
|{{c multi
 +
|log(a.size())
 +
|+ a.count(k)
 +
}}
 +
|-
 +
|{{c|a_tran.erase(kx)}}<br>{{mark since c++23}}
 +
|{{tt|size_type}}
 +
|
 +
|Erases all elements in the container with key {{c|r}} such that {{c|!c(r, kx) && !c(kx, r)}} is {{c|true}}
 +
|The number of erased elements
 +
|{{c multi
 +
|log(a_tran.size())
 +
|+ a_tran.count(kx)
 +
}}
 +
|-
 +
|{{c|a.erase(q)}}
 +
|{{tt|iterator}}
 +
|
 +
|Erases the element pointed to by {{c|q}}
 +
|An iterator pointing to the element immediately following {{c|q}} prior to the element being erased. If no such element exists, returns {{c|a.end()}}
 +
|Amortized constant
 +
|-
 +
|{{c|a.erase(r)}}
 +
|{{tt|iterator}}
 +
|
 +
|Erases the element pointed to by {{c|r}}
 +
|An iterator pointing to the element immediately following {{c|r}} prior to the element being erased. If no such element exists, returns {{c|a.end()}}
 +
|Amortized constant
 +
|-
 +
|{{c|a.erase(q1, q2)}}
 +
|{{tt|iterator}}
 +
|
 +
|Erases all the elements in the range<br>{{range|q1|q2}}
 +
|An iterator pointing to the element pointed to by {{c|q2}} prior to any elements being erased. If no such element exists, {{c|a.end()}} is returned
 +
|{{c|log(a.size()) + N}}, where {{tt|N}} has the value {{c|std::distance(q1, q2)}}
 +
|-
 +
|{{c|a.clear()}}
 +
|
 +
|
 +
|{{c|a.erase(a.begin(), a.end())}}. Ensures: {{c|a.empty()}} is {{c|true}}
 +
|
 +
|Linear in {{c|a.size()}}
 +
|-
 +
|{{c|b.find(k)}}
 +
|{{tt|iterator}}; {{tt|const_iterator}} for constant {{c|b}}
 +
|
 +
|
 +
|An iterator pointing to an element with the key equivalent to {{c|k}}, or {{c|b.end()}} if such an element is not found
 +
|Logarithmic
 +
|-
 +
|{{c|a_tran.find(ke)}}
 +
|{{tt|iterator}}; {{tt|const_iterator}} for constant {{c|a_tran}}
 +
|
 +
|
 +
|An iterator pointing to an element with key {{c|r}} such that
 +
{{c multi|
 +
!c(r, ke) &&|
 +
!c(ke, r)}}
 +
is {{c|true}}, or {{c|a_tran.end()}} if such an element is not found
 +
|Logarithmic
 +
|-
 +
|{{c|b.count(k)}}
 +
|{{tt|size_type}}
 +
|
 +
|
 +
|The number of elements with key equivalent to {{c|k}}
 +
|{{c multi
 +
|log(b.size())
 +
|+ b.count(k)
 +
}}
 +
|-
 +
|{{c|a_tran.count(ke)}}
 +
|{{tt|size_type}}
 +
|
 +
|
 +
|The number of elements with key {{c|r}} such that
 +
{{c multi|
 +
!c(r, ke) &&|
 +
!c(ke, r)}}
 +
|{{c multi
 +
|log(a_tran.size())
 +
|+ a_tran.count(ke)
 +
}}
 +
|-
 +
|{{c|b.contains(k)}}
 +
|{{c|bool}}
 +
|
 +
|{{c|1=return b.find(k) != b.end();}}
 +
|
 +
|<!--TODO: absent in 4950, present in IS C++20 Logarithmic-->
 +
|-
 +
|{{c|a_tran.contains(ke)}}
 +
|{{c|bool}}
 +
|
 +
|
 +
{{c multi
 +
|return
 +
|  a_tran.find(ke) !{{=}}
 +
|  a_tran.end();
 +
}}
 +
|
 +
|<!--TODO: absent in 4950, present in IS C++20 Logarithmic-->
 +
|-
 +
|{{c|b.lower_bound(k)}}
 +
|{{tt|iterator}}; {{tt|const_iterator}} for constant {{c|b}}
 +
|
 +
|
 +
|An iterator pointing to the first element with key not less than {{c|k}}, or {{c|b.end()}} if such an element is not found
 +
|Logarithmic
 +
|-
 +
|{{c|a_tran.lower_bound(kl)}}
 +
|{{tt|iterator}}; {{tt|const_iterator}} for constant {{c|a_tran}}
 +
|
 +
|
 +
|An iterator pointing to the first element with key {{c|r}} such that {{c|!c(r, kl)}}, or {{c|a_tran.end()}} if such an element is not found
 +
|Logarithmic
 +
|-
 +
|{{c|b.upper_bound(k)}}
 +
|{{tt|iterator}}; {{tt|const_iterator}} for constant {{c|b}}
 +
|
 +
|
 +
|An iterator pointing to the first element with key greater than {{c|k}}, or {{c|b.end()}} if such an element is not found
 +
|Logarithmic
 +
|-
 +
|{{c|a_tran.upper_bound(ku)}}
 +
|{{tt|iterator}}; {{tt|const_iterator}} for constant {{c|a_tran}}
 +
|
 +
|
 +
|An iterator pointing to the first element with key {{c|r}} such that {{c|c(ku, r)}}, or {{c|a_tran.end()}} if such an element is not found
 +
|Logarithmic
 +
|-
 +
|{{c|b.equal_range(k)}}
 +
|{{c multi
 +
|std::pair<
 +
|  iterator,
 +
|  iterator>
 +
}};
 +
{{c multi
 +
|std::pair<
 +
|  const_iterator,
 +
|  const_iterator>
 +
}}
 +
for constant {{c|b}}
 +
|
 +
|Equivalent to:
 +
{{c multi
 +
|return
 +
|  std::make_pair(
 +
|    b.lower_bound(k),
 +
|    b.upper_bound(k));
 +
}}
 +
|
 +
|Logarithmic
 +
|-
 +
|{{c|a_tran.equal_range(ke)}}
 +
|{{c multi
 +
|std::pair<
 +
|  iterator,
 +
|  iterator>
 +
}};
 +
{{c multi
 +
|std::pair<
 +
|  const_iterator,
 +
|  const_iterator>
 +
}}
 +
for constant {{c|a_tran}}
 +
|
 +
|Equivalent to:
 +
{{c multi
 +
|return
 +
|  std::make_pair(
 +
|    a_tran.lower_bound(ke),
 +
|    a_tran.upper_bound(ke));
 +
}}
 +
|
 +
|Logarithmic
 
|-
 
|-
 
|}
 
|}
 +
</div>
 +
 +
====Iterators====
 +
Iterators of associative containers satisfy the requirements of {{named req|BidirectionalIterator}}.
 +
 +
For associative containers where {{tt|value_type}} is the same as {{tt|key_type}}, both {{tt|iterator}} and {{tt|const_iterator}} are constant iterators. It is unspecified whether or not {{tt|iterator}} and {{tt|const_iterator}} are the same type.
  
An associative container {{ttb|X}} that is either {{ttb|std::map}} and {{ttb|std::multimap}} additionally supports the expression X::mapped_type, which has a return type of T, with the requirement that {{ttb|T}} be {{named req|Destructible}}, and compile time complexity.
+
Iterators of associative containers iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct the containers. That is, given
 +
* {{c|a}}, an associative container
 +
* {{c|i}} and {{c|j}}, dereferenceable iterators to {{c|a}}.
 +
If the distance from {{c|i}} to {{c|j}} is positive, then {{c|1=a.value_comp()(*j, *i) == false}}. Additionally, if {{c|a}} is an associative container with unique keys, the stronger condition {{c|1=a.value_comp()(*i, *j) != false}} holds.
  
 
{{todo|Finish requirements.}}
 
{{todo|Finish requirements.}}
Line 65: Line 510:
 
===Associative containers in the standard library===
 
===Associative containers in the standard library===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/container/dsc set}}
+
{{dsc inc|cpp/container/dsc set}}
{{dsc inc | cpp/container/dsc multiset}}
+
{{dsc inc|cpp/container/dsc multiset}}
{{dsc inc | cpp/container/dsc map}}
+
{{dsc inc|cpp/container/dsc map}}
{{dsc inc | cpp/container/dsc multimap}}
+
{{dsc inc|cpp/container/dsc multimap}}
 
{{dsc end}}
 
{{dsc end}}
  
Line 74: Line 519:
 
{{dr list begin}}
 
{{dr list begin}}
 
{{dr list item|wg=lwg|dr=354|std=C++98|before={{tt|lower_bound}} and {{tt|upper_bound}} did not<br>return the end iterator if no element is found|after=they return the end<br>iterator in this case}}
 
{{dr list item|wg=lwg|dr=354|std=C++98|before={{tt|lower_bound}} and {{tt|upper_bound}} did not<br>return the end iterator if no element is found|after=they return the end<br>iterator in this case}}
 +
{{dr list item|wg=lwg|dr=589|std=C++98|before=the elements that {{c|i}} and {{c|j}} refer<br>to had the type {{tt|X::value_type}}|after=the elements are implicitly<br>convertible to {{tt|X::value_type}}}}
 
{{dr list end}}
 
{{dr list end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 04:27, 4 August 2024

 
 
C++ named requirements
 

An AssociativeContainer is an ordered Container that provides fast lookup of objects based on keys.

An associative container supports unique keys if it may contain at most one element for each key. Otherwise, it supports equivalent keys.

Contents

[edit] Requirements

Legend
X An associative container class
T The element type of X
A The allocator type of X: X::allocator_type if it exists, otherwise std::allocator<X::value_type>
a A value of type X
a2 A value of a type Y whose node handles are compatible with X
b A value of type X or const X
u A name of a variable beging declared
a_uniq A value of type X when X supports unique keys
a_eq A value of type X when X supports equivalent keys
a_tran A value of type X or const X when type X::key_compare::is_transparent exists
i, j The LegacyInputIterators referring to elements implicitly convertible to X::value_type
[ij) A valid range
rg
(since C++23)
A value of a type R that models container-compatible-range<value_type>
p A valid constant iterator to a
q A valid dereferenceable constant iterator to a
r A valid dereferenceable iterator to a
q1, q2 A valid range of const iterators in a
il An object of type std::initializer_list<X::value_type>
t A value of type X::value_type
k A value of type X::key_type
c A value of type X::key_compare or const X::key_compare
kl A value such that a is partitioned with respect to c(x, kl), with x the key value of e and e in a
ku A value such that a is partitioned with respect to !c(ku, x), with x the key value of e and e in a
ke A value such that a is partitioned with respect to c(x, ke) and !c(ke, x), with c(x, ke) implying !c(ke, x) and with x the key value of e and e in a
kx
(since C++23)
A value such that:
  • a is partitioned with respect to c(x, kx) and !c(kx, x), with c(x, kx) implying !c(kx, x) and with x the key value of e and e in a, and
  • kx is not convertible to either X::iterator or X::const_iterator
m An allocator of a type convertible to A
nh A non-const rvalue of type X::node_type

The type X satisfies AssociativeContainer if

  • The type X satisfies Container(until C++11)AllocatorAwareContainer(since C++11),
  • Is parameterized on Key and an ordering relation Compare that induces a strict weak ordering on elements of Key, and
    • In addition, std::map and std::multimap associate an arbitrary mapped type T with the Key.
    • The object of type Compare is called the comparison object of a container of type X.
  • The following expressions must be valid and have their specified effects for all associative containers:

[edit] Types

Name Type Requirements
key_type Key
mapped_type T (for std::map and std::multimap only)
value_type Erasable from X
key_compare Compare CopyConstructible
value_compare BinaryPredicate
node_type A specialization of the node-handle class template, such that the public nested types are the same types as the corresponding types in X.

[edit] Member functions and operators

Expression Result Preconditions Effects Returns Complexity
X(c) Constructs an empty container. Uses a copy of c as a comparison object Constant
X u = X();
X u;
key_compare meets the DefaultConstructible requirements Constructs an empty container. Uses Compare() as a comparison object Constant
X(i, j, c) value_type is EmplaceConstructible into X from *i Constructs an empty container and inserts elements from the range [ij) into it; uses c as a comparison object N·log(N) in general, where N has the value std::distance(i, j); linear if [ij) is sorted with respect to value_comp()
X(i, j) key_compare meets the DefaultConstructible requirements. value_type is EmplaceConstructible into X from *i Constructs an empty container and inserts elements from the range [ij) into it; uses Compare() as a comparison object
X(from_range, rg, c)
(since C++23)
value_type is EmplaceConstructible into X from *ranges::begin(rg) Constructs an empty container and inserts each element from rg into it. Uses c as the comparison object N·log(N) in general, where N has the value ranges::distance(rg); linear if rg is sorted with respect to value_comp()
X(from_range, rg)
(since C++23)
key_compare meets the DefaultConstructible requirements. value_type is EmplaceConstructible into X from *ranges::begin(rg) Constructs an empty container and inserts each element from rg into it. Uses Compare() as the comparison object
X(il, c) X(il.begin(), il.end(), c)
X(il) X(il.begin(), il.end())
a = il X& value_type is CopyInsertable into X and CopyAssignable Assigns the range [il.begin()il.end()) into a. All existing elements of a are either assigned to or destroyed N·log(N) in general, where N has the value il.size() + a.size(); linear if [il.begin()il.end()) is sorted with respect to value_comp()
b.key_comp() X::key_compare The comparison object out of which b was constructed Constant
b.value_comp() X::value_compare An object of value_compare constructed out of the comparison object Constant
a_uniq.emplace(args) std::pair<
  iterator,
  bool>
value_type is EmplaceConstructible into X from args Inserts a value_type object t constructed with std::forward<Args>(args)... if and only if there is no element in the container with key equivalent to the key of t The bool component of the returned pair is true if and only if the insertion takes place, and the iterator component of the pair points to the element with key equivalent to the key of t Logarithmic
a_eq.emplace(args) iterator value_type is EmplaceConstructible into X from args Inserts a value_type object t constructed with std::forward<Args>(args).... If a range containing elements equivalent to t exists in a_eq, t is inserted at the end of that range An iterator pointing to the newly inserted element Logarithmic
a.emplace_hint(p, args) iterator Equivalent to

a.emplace(
  std::forward<Args>(args)...)
, except that the element is inserted as close as possible to the position just prior to p

An iterator pointing to the element with the key equivalent to the newly inserted element Logarithmic in general, but amortized constant if the element is inserted right before p
a_uniq.insert(t) std::pair<
  iterator,
  bool>
If t is a non-const rvalue, value_type is MoveInsertable into X; otherwise, value_type is CopyInsertable into X Inserts t if and only if there is no element in the container with key equivalent to the key of t The bool component of the returned pair is true if and only if the insertion takes place, and the iterator component of the pair points to the element with key equivalent to the key of t Logarithmic
a_eq.insert(t) iterator If t is a non-const rvalue, value_type is MoveInsertable into X; otherwise, value_type is CopyInsertable into X Inserts t and returns the iterator pointing to the newly inserted element. If a range containing elements equivalent to t exists in a_eq, t is inserted at the end of that range Logarithmic
a.insert(p, t) iterator If t is a non-const rvalue, value_type is MoveInsertable into X; otherwise, value_type is CopyInsertable into X Inserts t if and only if there is no element with key equivalent to the key of t in containers with unique keys; always inserts t in containers with equivalent keys. t is inserted as close as possible to the position just prior to p An iterator pointing to the element with key equivalent to the key of t Logarithmic in general, but amortized constant if t is inserted right before p
a.insert(i, j) void value_type is EmplaceConstructible into X from *i. Neither i nor j are iterators into a Inserts each element from the range [ij) if and only if there is no element with key equivalent to the key of that element in containers with unique keys; always inserts that element in containers with equivalent keys N·log(a.size() + N), where N has the value std::distance(i, j)
a.insert_range(rg)
(since C++23)
void value_type is EmplaceConstructible into X from *ranges::begin(rg). rg and a do not overlap Inserts each element from rg if and only if there is no element with key equivalent to the key of that element in containers with unique keys; always inserts that element in containers with equivalent keys N·log(a.size() + N), where N has the value ranges::distance(rg)
a.insert(il) a.insert(il.begin(), il.end())
a_uniq.insert(nh) insert_return_type nh is empty or

a_uniq.get_allocator()
==
nh.get_allocator()
is true

If nh is empty, has no effect. Otherwise, inserts the element owned by nh if and only if there is no element in the container with a key equivalent to nh.key() If nh is empty, inserted is false, position is end(), and node is empty. Otherwise if the insertion took place, inserted is true, position points to the inserted element, and node is empty; if the insertion failed, inserted is false, node has the previous value of nh, and position points to an element with a key equivalent to nh.key() Logarithmic
a_eq.insert(nh) iterator nh is empty or

a_eq.get_allocator()
==
nh.get_allocator()
is true

If nh is empty, has no effect and returns a_eq.end(). Otherwise, inserts the element owned by nh and returns an iterator pointing to the newly inserted element. If a range containing elements with keys equivalent to nh.key() exists in a_eq, the element is inserted at the end of that range. Ensures: nh is empty Logarithmic
a.insert(p, nh) iterator nh is empty or

a.get_allocator()
==
nh.get_allocator()
is true

If nh is empty, has no effect and returns a.end(). Otherwise, inserts the element owned by nh if and only if there is no element with key equivalent to nh.key() in containers with unique keys; always inserts the element owned by nh in containers with equivalent keys. The element is inserted as close as possible to the position just prior to p. Ensures: nh is empty if insertion succeeds, unchanged if insertion fails An iterator pointing to the element with key equivalent to nh.key() Logarithmic in general, but amortized constant if the element is inserted right before p
a.extract(k) node_type Removes the first element in the container with key equivalent to k A node_type owning the element if found, otherwise an empty node_type log(a.size())
a_tran.extract(kx)
(since C++23)
node_type Removes the first element in the container with key r such that !c(r, kx) && !c(kx, r) is true A node_type owning the element if found, otherwise an empty node_type log(a_tran.size())
a.extract(q) node_type Removes the element pointed to by q A node_type owning that element Amortized constant
a.merge(a2) void a.get_allocator()
==
a2.get_allocator()
Attempts to extract each element in a2 and insert it into a using the comparison object of a. In containers with unique keys, if there is an element in a with key equivalent to the key of an element from a2, then that element is not extracted from a2. Ensures: Pointers and references to the transferred elements of a2 refer to those same elements but as members of a. Iterators referring to the transferred elements will continue to refer to their elements, but they now behave as iterators into a, not into a2. Throws: Nothing unless the comparison object throws N·log(a.size() + N), where N has the value a2.size()
a.erase(k) size_type Erases all elements in the container with key equivalent to k The number of erased elements log(a.size())
+ a.count(k)
a_tran.erase(kx)
(since C++23)
size_type Erases all elements in the container with key r such that !c(r, kx) && !c(kx, r) is true The number of erased elements log(a_tran.size())
+ a_tran.count(kx)
a.erase(q) iterator Erases the element pointed to by q An iterator pointing to the element immediately following q prior to the element being erased. If no such element exists, returns a.end() Amortized constant
a.erase(r) iterator Erases the element pointed to by r An iterator pointing to the element immediately following r prior to the element being erased. If no such element exists, returns a.end() Amortized constant
a.erase(q1, q2) iterator Erases all the elements in the range
[q1q2)
An iterator pointing to the element pointed to by q2 prior to any elements being erased. If no such element exists, a.end() is returned log(a.size()) + N, where N has the value std::distance(q1, q2)
a.clear() a.erase(a.begin(), a.end()). Ensures: a.empty() is true Linear in a.size()
b.find(k) iterator; const_iterator for constant b An iterator pointing to an element with the key equivalent to k, or b.end() if such an element is not found Logarithmic
a_tran.find(ke) iterator; const_iterator for constant a_tran An iterator pointing to an element with key r such that

!c(r, ke) &&
!c(ke, r)
is true, or a_tran.end() if such an element is not found

Logarithmic
b.count(k) size_type The number of elements with key equivalent to k log(b.size())
+ b.count(k)
a_tran.count(ke) size_type The number of elements with key r such that

!c(r, ke) &&
!c(ke, r)

log(a_tran.size())
+ a_tran.count(ke)
b.contains(k) bool return b.find(k) != b.end();
a_tran.contains(ke) bool

return
  a_tran.find(ke) !=
  a_tran.end();

b.lower_bound(k) iterator; const_iterator for constant b An iterator pointing to the first element with key not less than k, or b.end() if such an element is not found Logarithmic
a_tran.lower_bound(kl) iterator; const_iterator for constant a_tran An iterator pointing to the first element with key r such that !c(r, kl), or a_tran.end() if such an element is not found Logarithmic
b.upper_bound(k) iterator; const_iterator for constant b An iterator pointing to the first element with key greater than k, or b.end() if such an element is not found Logarithmic
a_tran.upper_bound(ku) iterator; const_iterator for constant a_tran An iterator pointing to the first element with key r such that c(ku, r), or a_tran.end() if such an element is not found Logarithmic
b.equal_range(k) std::pair<
  iterator,
  iterator>
;

std::pair<
  const_iterator,
  const_iterator>
for constant b

Equivalent to:

return
  std::make_pair(
    b.lower_bound(k),
    b.upper_bound(k));

Logarithmic
a_tran.equal_range(ke) std::pair<
  iterator,
  iterator>
;

std::pair<
  const_iterator,
  const_iterator>
for constant a_tran

Equivalent to:

return
  std::make_pair(
    a_tran.lower_bound(ke),
    a_tran.upper_bound(ke));

Logarithmic

[edit] Iterators

Iterators of associative containers satisfy the requirements of LegacyBidirectionalIterator.

For associative containers where value_type is the same as key_type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type.

Iterators of associative containers iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct the containers. That is, given

  • a, an associative container
  • i and j, dereferenceable iterators to a.

If the distance from i to j is positive, then a.value_comp()(*j, *i) == false. Additionally, if a is an associative container with unique keys, the stronger condition a.value_comp()(*i, *j) != false holds.

[edit] Associative containers in the standard library

collection of unique keys, sorted by keys
(class template) [edit]
collection of keys, sorted by keys
(class template) [edit]
collection of key-value pairs, sorted by keys, keys are unique
(class template) [edit]
collection of key-value pairs, sorted by keys
(class template) [edit]

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 354 C++98 lower_bound and upper_bound did not
return the end iterator if no element is found
they return the end
iterator in this case
LWG 589 C++98 the elements that i and j refer
to had the type X::value_type
the elements are implicitly
convertible to X::value_type