std::__debug(3cxx)
π std::__debug π
okay bestie, so this page is from the 3cxx manual (that's the C++ docs section, iykyk), and it's literally about std::__debug.
β¨ NAME β¨
std::__debug β GNU debug code, which replaces standard behavior with debug behavior. that's the whole vibe: same energy, but now with safety checks on top π
πΈ SYNOPSIS πΈ
π¦ Classes
okay so this is the part where it gets iconic β every one of these is the same class you already know and love, except it's been given the debug-instrumentation glow-up β¨ like, the standard container you know, but now it's checking on you π«Ά
class bitsetβ Classstd::bitsetwith additional safety/checking/debug instrumentation. πclass dequeβ Classstd::dequewith safety/checking/debug instrumentation.class forward_listβ Classstd::forward_listwith safety/checking/debug instrumentation.class listβ Classstd::listwith safety/checking/debug instrumentation.class mapβ Classstd::mapwith safety/checking/debug instrumentation.class multimapβ Classstd::multimapwith safety/checking/debug instrumentation.class multisetβ Classstd::multisetwith safety/checking/debug instrumentation.class setβ Classstd::setwith safety/checking/debug instrumentation.class unordered_mapβ Classstd::unordered_mapwith safety/checking/debug instrumentation. π₯class unordered_multimapβ Classstd::unordered_multimapwith safety/checking/debug instrumentation.class unordered_multisetβ Classstd::unordered_multisetwith safety/checking/debug instrumentation.class unordered_setβ Classstd::unordered_setwith safety/checking/debug instrumentation. βclass vectorβ Classstd::vectorwith safety/checking/debug instrumentation. π
ngl the way every single one of these is just "the class, but with instrumentation" is giving very consistent, very main character energy π no cap, that's the whole list β every container got the same treatment, nobody left out π
so the Functions list is long long, and it's basically every free function + deduction guide that plays nice with the debug containers. Buckle up bestie, we're going container by container π
π«Ά the deduction guides (aka "yes, deque d(first, last) just works")
deque, guide numero uno β the iterator-range one β¨
template<typename _InputIterator, typename _ValT = typename iterator_traits<_InputIterator>::value_type, typename _Allocator = allocator<_ValT>, typename = _RequireInputIter<_InputIterator>, typename = _RequireAllocator<_Allocator>>
deque(_InputIterator, _InputIterator, _Allocator=_Allocator()) -> deque<_ValT, _Allocator>
deque, guide numero dos β the size_t-plus-value one πΈ
template<typename _Tp, typename _Allocator = allocator<_Tp>, typename = _RequireAllocator<_Allocator>>
deque(size_t, _Tp, _Allocator=_Allocator()) -> deque<_Tp, _Allocator>
forward_list, iterator-range flavor π¦
template<typename _InputIterator, typename _ValT = typename iterator_traits<_InputIterator>::value_type, typename _Allocator = allocator<_ValT>, typename = _RequireInputIter<_InputIterator>, typename = _RequireAllocator<_Allocator>>
forward_list(_InputIterator, _InputIterator, _Allocator=_Allocator()) -> forward_list<_ValT, _Allocator>
forward_list, size_t-plus-value flavor π¦
template<typename _Tp, typename _Allocator = allocator<_Tp>, typename = _RequireAllocator<_Allocator>>
forward_list(size_t, _Tp, _Allocator=_Allocator()) -> forward_list<_Tp, _Allocator>
list, iterator-range one π
template<typename _InputIterator, typename _ValT = typename iterator_traits<_InputIterator>::value_type, typename _Allocator = allocator<_ValT>, typename = _RequireInputIter<_InputIterator>, typename = _RequireAllocator<_Allocator>>
list(_InputIterator, _InputIterator, _Allocator=_Allocator()) -> list<_ValT, _Allocator>
list, size_t-plus-value one π
template<typename _Tp, typename _Allocator = allocator<_Tp>, typename = _RequireAllocator<_Allocator>>
list(size_t, _Tp, _Allocator=_Allocator()) -> list<_Tp, _Allocator>
notice how every one of these has_RequireInputIterand/or_RequireAllocatorhanging out in the parameter list β that's the "bestie pls, don't hand me a non-input-iterator" guard rail β¨
π map guides β four of them, no skips
template<typename _InputIterator, typename _Allocator, typename = _RequireInputIter<_InputIterator>, typename = _RequireAllocator<_Allocator>>
map(_InputIterator, _InputIterator, _Allocator) -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, less<__iter_key_t<_InputIterator>>, _Allocator>
template<typename _InputIterator, typename _Compare = less<__iter_key_t<_InputIterator>>, typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, typename = _RequireInputIter<_InputIterator>, typename = _RequireNotAllocator<_Compare>, typename = _RequireAllocator<_Allocator>>
map(_InputIterator, _InputIterator, _Compare=_Compare(), _Allocator=_Allocator()) -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare, _Allocator>
template<typename _Key, typename _Tp, typename _Allocator, typename = _RequireAllocator<_Allocator>>
map(initializer_list<pair<_Key, _Tp>>, _Allocator) -> map<_Key, _Tp, less<_Key>, _Allocator>
template<typename _Key, typename _Tp, typename _Compare = less<_Key>, typename _Allocator = allocator<pair<const _Key, _Tp>>, typename = _RequireNotAllocator<_Compare>, typename = _RequireAllocator<_Allocator>>
map(initializer_list<pair<_Key, _Tp>>, _Compare=_Compare(), _Allocator=_Allocator()) -> map<_Key, _Tp, _Compare, _Allocator>
π multimap guides β same energy, but make it multi
template<typename _InputIterator, typename _Allocator, typename = _RequireInputIter<_InputIterator>, typename = _RequireAllocator<_Allocator>>
multimap(_InputIterator, _InputIterator, _Allocator) -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, less<__iter_key_t<_InputIterator>>, _Allocator>
template<typename _InputIterator, typename _Compare = less<__iter_key_t<_InputIterator>>, typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, typename = _RequireInputIter<_InputIterator>, typename = _RequireNotAllocator<_Compare>, typename = _RequireAllocator<_Allocator>>
multimap(_InputIterator, _InputIterator, _Compare=_Compare(), _Allocator=_Allocator()) -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare, _Allocator>
template<typename _Key, typename _Tp, typename _Allocator, typename = _RequireAllocator<_Allocator>>
multimap(initializer_list<pair<_Key, _Tp>>, _Allocator) -> multimap<_Key, _Tp, less<_Key>, _Allocator>
template<typename _Key, typename _Tp, typename _Compare = less<_Key>, typename _Allocator = allocator<pair<const _Key, _Tp>>, typename = _RequireNotAllocator<_Compare>, typename = _RequireAllocator<_Allocator>>
multimap(initializer_list<pair<_Key, _Tp>>, _Compare=_Compare(), _Allocator=_Allocator()) -> multimap<_Key, _Tp, _Compare, _Allocator>
π multiset guides β four again, because we love consistency
template<typename _InputIterator, typename _Allocator, typename = _RequireInputIter<_InputIterator>, typename = _RequireAllocator<_Allocator>>
multiset(_InputIterator, _InputIterator, _Allocator) -> multiset<typename iterator_traits<_InputIterator>::value_type, less<typename iterator_traits<_InputIterator>::value_type>, _Allocator>
template<typename _InputIterator, typename _Compare = less<typename iterator_traits<_InputIterator>::value_type>, typename _Allocator = allocator<typename iterator_traits<_InputIterator>::value_type>, typename = _RequireInputIter<_InputIterator>, typename = _RequireNotAllocator<_Compare>, typename = _RequireAllocator<_Allocator>>
multiset(_InputIterator, _InputIterator, _Compare=_Compare(), _Allocator=_Allocator()) -> multiset<typename iterator_traits<_InputIterator>::value_type, _Compare, _Allocator>
template<typename _Key, typename _Allocator, typename = _RequireAllocator<_Allocator>>
multiset(initializer_list<_Key>, _Allocator) -> multiset<_Key, less<_Key>, _Allocator>
template<typename _Key, typename _Compare = less<_Key>, typename _Allocator = allocator<_Key>, typename = _RequireNotAllocator<_Compare>, typename = _RequireAllocator<_Allocator>>
multiset(initializer_list<_Key>, _Compare=_Compare(), _Allocator=_Allocator()) -> multiset<_Key, _Compare, _Allocator>
lowkey a flex thatmultisetspells outtypename iterator_traits<_InputIterator>::value_typein full instead of using a helper alias. she's verbose but she's honest π
β¨ bitset operators β tiny but iconic
bitwise AND, constexpr and noexcept, she's got it all π
template<size_t _Nb> constexpr bitset<_Nb> operator&(const bitset<_Nb> &__x, const bitset<_Nb> &__y) noexcept
stream insertion, so you can actually print your bits π₯
template<typename _CharT, typename _Traits, size_t _Nb>
std::basic_ostream<_CharT, _Traits> &operator<<(std::basic_ostream<_CharT, _Traits> &__os, const bitset<_Nb> &__x)
bitwise XOR, same constexpr + noexcept treatment π«
template<size_t _Nb> constexpr bitset<_Nb> operator^(const bitset<_Nb> &__x, const bitset<_Nb> &__y) noexcept
bitwise OR, rounding out the trio πΈ
template<size_t _Nb> constexpr bitset<_Nb> operator|(const bitset<_Nb> &__x, const bitset<_Nb> &__y) noexcept
heads up: operator<< here is the stream one, not a shift. don't get it twisted bestie π«Ά
π§ the spaceship operator <=> squad
three-way comparison, but make it every container. note which ones get constexpr and which onesβ¦ don't π
template<typename _Tp, typename _Alloc> constexpr __detail::__synth3way_t<_Tp> operator<=>(const deque<_Tp, _Alloc> &__x, const deque<_Tp, _Alloc> &__y)
template<typename _Tp, typename _Alloc> constexpr __detail::__synth3way_t<_Tp> operator<=>(const forward_list<_Tp, _Alloc> &__x, const forward_list<_Tp, _Alloc> &__y)
template<typename _Tp, typename _Alloc> constexpr __detail::__synth3way_t<_Tp> operator<=>(const list<_Tp, _Alloc> &__x, const list<_Tp, _Alloc> &__y)
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> __detail::__synth3way_t<pair<const _Key, _Tp>> operator<=>(const map<_Key, _Tp, _Compare, _Alloc> &__lhs, const map<_Key, _Tp, _Compare, _Alloc> &__rhs)
template<typename _Key, typename _Tp, typename _Compare, typename _Alloc> __detail::__synth3way_t<pair<const _Key, _Tp>> operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc> &__lhs, const multimap<_Key, _Tp, _Compare, _Alloc> &__rhs)
template<typename _Key, typename _Compare, typename _Alloc> __detail::__synth3way_t<_Key> operator<=>(const multiset<_Key, _Compare, _Alloc> &__lhs, const multiset<_Key, _Compare, _Alloc> &__rhs)
template<typename _Key, typename _Compare, typename _Alloc> __detail::__synth3way_t<_Key> operator<=>(const set<_Key, _Compare, _Alloc> &__lhs, const set<_Key, _Compare, _Alloc> &__rhs)
template<typename _Tp, typename _Alloc> constexpr __detail::__synth3way_t<_Tp> operator<=>(const vector<_Tp, _Alloc> &__x, const vector<_Tp, _Alloc> &__y)
the<=>ones formap,multimap,multisetandsethave noconstexprin front of them. that's not me being sloppy, that's literally how it's written.deque,forward_list,listandvectorall keep theirs. iykyk π
π operator== β the whole friend group
template<typename _Tp, typename _Alloc> bool operator==(const deque<_Tp, _Alloc> &__lhs, const deque<_Tp, _Alloc> &__rhs)
template<typename _Tp, typename _Alloc> bool operator==(const forward_list<_Tp, _Alloc> &__lx, const forward_list<_Tp, _Alloc> &__ly)
template<typename _Tp, typename _Alloc> bool operator==(const list<_Tp, _Alloc> &__lhs, const list<_Tp, _Alloc> &__rhs)
template<typename _Key, typename _Tp, typename _Compare, typename _Allocator> bool operator==(const map<_Key, _Tp, _Compare, _Allocator> &__lhs, const map<_Key, _Tp, _Compare, _Allocator> &__rhs)
template<typename _Key, typename _Tp, typename _Compare, typename _Allocator> bool operator==(const multimap<_Key, _Tp, _Compare, _Allocator> &__lhs, const multimap<_Key, _Tp, _Compare, _Allocator> &__rhs)
template<typename _Key, typename _Compare, typename _Allocator> bool operator==(const multiset<_Key, _Compare, _Allocator> &__lhs, const multiset<_Key, _Compare, _Allocator> &__rhs)
template<typename _Key, typename _Compare, typename _Allocator> bool operator==(const set<_Key, _Compare, _Allocator> &__lhs, const set<_Key, _Compare, _Allocator> &__rhs)
and now the unordered girlies, who use _Hash and _Pred and _Value instead of _Compare β main character naming choices π
template<typename _Key, typename _Tp, typename _Hash, typename _Pred, typename _Alloc> bool operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> &__x, const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> &__y)
template<typename _Key, typename _Tp, typename _Hash, typename _Pred, typename _Alloc> bool operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> &__x, const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> &__y)
template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> bool operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc> &__x, const unordered_multiset<_Value, _Hash, _Pred, _Alloc> &__y)
template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> bool operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc> &__x, const unordered_set<_Value, _Hash, _Pred, _Alloc> &__y)
and finally vector, the only one of the == crew rocking constexpr β
template<typename _Tp, typename _Alloc> constexpr bool operator==(const vector<_Tp, _Alloc> &__lhs, const vector<_Tp, _Alloc> &__rhs)
also peep thatforward_list's==uses__lxand__lywhile everyone else uses__lhs/__rhs. yes queen, be different π¦
π and one more stream operator, for reading your bits back in
template<typename _CharT, typename _Traits, size_t _Nb>
std::basic_istream<_CharT, _Traits> &operator>>(std::basic_istream<_CharT, _Traits> &__is, bitset<_Nb> &__x)
okay that's the entire Functions roster and honestly? she ate π
but there's more page left, so don't go anywhere β
okay so we're still deep in the synopsis, and now we hit the part where deduction guides show up β they're the -> bits, the little arrows that let the compiler figure out all your template args for you so you don't have to type set<std::string, std::less<std::string>, std::allocator<std::string>> like some kind of Victorian ghost π they're lowkey the main character of C++17 and nobody talks about them π
first up, set π
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> set (_InputIterator, _InputIterator,
_Allocator) -> set< typename iterator_traits< _InputIterator
>::value_type, less< typename iterator_traits< _InputIterator
>::value_type >, _Allocator >
template<typename _InputIterator , typename _Compare = less<typename
iterator_traits<_InputIterator>::value_type>, typename _Allocator =
allocator<typename iterator_traits<_InputIterator>::value_type>,
typename = _RequireInputIter<_InputIterator>, typename =
_RequireNotAllocator<_Compare>, typename =
_RequireAllocator<_Allocator>> set (_InputIterator, _InputIterator,
_Compare=_Compare(), _Allocator=_Allocator()) -> set< typename
iterator_traits< _InputIterator >::value_type, _Compare, _Allocator
>
template<typename _Key , typename _Allocator , typename =
_RequireAllocator<_Allocator>> set (initializer_list< _Key >,
_Allocator) -> set< _Key, less< _Key >, _Allocator >
template<typename _Key , typename _Compare = less<_Key>, typename
_Allocator = allocator<_Key>, typename =
_RequireNotAllocator<_Compare>, typename =
_RequireAllocator<_Allocator>> set (initializer_list< _Key >,
_Compare=_Compare(), _Allocator=_Allocator()) -> set< _Key,
_Compare, _Allocator >
see how they all end in -> set< ... >? that's the payoff, bestie β¨ you hand it iterators or a initializer_list, it hands you back a fully-formed set type, no <...> typing required. and those _RequireInputIter, _RequireNotAllocator, _RequireAllocator things are just gatekeepers making sure you didn't pass an allocator where a comparator goes π the _RequireNotAllocator<_Compare> is literally there so set(it, it, some_allocator) doesn't get confused between the two guides, iykyk π
okay now the swap era π every single container gets a free-function swap, and they all take two of the same container by reference and swap them. watch the noexcept clauses because those are the gossip π
template<typename _Tp , typename _Alloc > void swap (deque< _Tp, _Alloc
> &__lhs, deque< _Tp, _Alloc > &__rhs) noexcept(/*conditional */)
template<typename _Tp , typename _Alloc > void swap (forward_list< _Tp,
_Alloc > &__lx, forward_list< _Tp, _Alloc > &__ly)
noexcept(noexcept(__lx.swap(__ly)))
See std::forward_list::swap().
template<typename _Tp , typename _Alloc > void swap (list< _Tp, _Alloc >
&__lhs, list< _Tp, _Alloc > &__rhs) noexcept(/*conditional */)
template<typename _Key , typename _Tp , typename _Compare , typename
_Allocator > void swap (map< _Key, _Tp, _Compare, _Allocator >
&__lhs, map< _Key, _Tp, _Compare, _Allocator > &__rhs)
noexcept(/*conditional */)
template<typename _Key , typename _Tp , typename _Compare , typename
_Allocator > void swap (multimap< _Key, _Tp, _Compare, _Allocator >
&__lhs, multimap< _Key, _Tp, _Compare, _Allocator > &__rhs)
noexcept(/*conditional */)
the deque, list, map and multimap ones all rock that noexcept(/*conditional */) β conditional meaning "it depends on whether the underlying allocator/comparator swap is noexcept, don't ask me, ask the standard" π
the forward_list one is the special little icon though β it's noexcept(noexcept(__lx.swap(__ly))), i.e. it's noexcept exactly when member swap is, and the manpage literally says See std::forward_list::swap(). so go read that one for the deets π«Ά
template<typename _Key , typename _Compare , typename _Allocator > void
swap (multiset< _Key, _Compare, _Allocator > &__x, multiset< _Key,
_Compare, _Allocator > &__y) noexcept(/*conditional */)
template<typename _Key , typename _Compare , typename _Allocator > void
swap (set< _Key, _Compare, _Allocator > &__x, set< _Key, _Compare,
_Allocator > &__y) noexcept(/*conditional */)
multiset and set, same deal, same noexcept(/*conditional */), and note the parameter names switch to __x and __y here β the map/deque/list ones used __lhs/__rhs, forward_list used __lx/__ly. not a typo, that's just how they wrote it, don't come for me πΈ
template<typename _Key , typename _Tp , typename _Hash , typename _Pred
, typename _Alloc > void swap (unordered_map< _Key, _Tp, _Hash,
_Pred, _Alloc > &__x, unordered_map< _Key, _Tp, _Hash, _Pred, _Alloc
> &__y) noexcept(noexcept(__x.swap(__y)))
template<typename _Key , typename _Tp , typename _Hash , typename _Pred
, typename _Alloc > void swap (unordered_multimap< _Key, _Tp, _Hash,
_Pred, _Alloc > &__x, unordered_multimap< _Key, _Tp, _Hash, _Pred,
_Alloc > &__y) noexcept(noexcept(__x.swap(__y)))
template<typename _Value , typename _Hash , typename _Pred , typename
_Alloc > void swap (unordered_multiset< _Value, _Hash, _Pred, _Alloc
> &__x, unordered_multiset< _Value, _Hash, _Pred, _Alloc > &__y)
noexcept(noexcept(__x.swap(__y)))
template<typename _Value , typename _Hash , typename _Pred , typename
_Alloc > void swap (unordered_set< _Value, _Hash, _Pred, _Alloc >
&__x, unordered_set< _Value, _Hash, _Pred, _Alloc > &__y)
noexcept(noexcept(__x.swap(__y)))
all four unordered ones are the confident siblings β no mysterious /*conditional */ for them, it's straight up noexcept(noexcept(__x.swap(__y))), they know exactly when they're noexcept and they're not shy about it π
also peep that unordered_set/unordered_multiset name their template param _Value while the map ones use _Key and _Tp β iconic inconsistency, we stan π
template<typename _Tp , typename _Alloc > constexpr void swap (vector<
_Tp, _Alloc > &__lhs, vector< _Tp, _Alloc > &__rhs)
noexcept(/*conditional */)
and vector! it's the only one blessed with constexpr before the void π yes bestie, constexpr swap, that's the whole vibe, back to __lhs/__rhs naming and back to noexcept(/*conditional */) π
next: the unordered_map deduction guides, and there are like a million of them π okay not a million, but enough that you're gonna want to sit down. they all follow the pattern of "figure out key type from the iterator, figure out value type from the iterator, pick defaults for hash/equal_to, use your allocator."
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> unordered_map (_InputIterator,
_InputIterator, _Allocator) -> unordered_map< __iter_key_t<
_InputIterator >, __iter_val_t< _InputIterator >, hash<
__iter_key_t< _InputIterator > >, equal_to< __iter_key_t<
_InputIterator > >, _Allocator >
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> unordered_map (_InputIterator,
_InputIterator, typename unordered_map< int, int >::size_type,
_Allocator) -> unordered_map< __iter_key_t< _InputIterator >,
__iter_val_t< _InputIterator >, hash< __iter_key_t< _InputIterator >
>, equal_to< __iter_key_t< _InputIterator > >, _Allocator >
template<typename _InputIterator , typename _Hash , typename _Allocator
, typename = _RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireAllocator<_Allocator>> unordered_map (_InputIterator,
_InputIterator, typename unordered_map< int, int >::size_type,
_Hash, _Allocator) -> unordered_map< __iter_key_t< _InputIterator >,
__iter_val_t< _InputIterator >, _Hash, equal_to< __iter_key_t<
_InputIterator > >, _Allocator >
okay two things to notice, and they're both giving template metaprogramming π
__iter_key_t<_InputIterator>and__iter_val_t<_InputIterator>are the internal helpers that pull the key and mapped type out of whatever iterator you fed it β that's how the guide knows what map you're building without you saying it π¦- the bucket-count parameter is spelled as
typename unordered_map< int, int >::size_typeβ a whole dummyunordered_map< int, int >just to borrow itssize_type. that's not me being extra, that's literally what the page says πΈ
also _RequireNotAllocatorOrIntegral<_Hash> is the bouncer making sure the third arg is genuinely a hash and not an allocator or an integer that wandered in π the _RequireInputIter and _RequireAllocator are doing their usual vibe check on the other slots.
template<typename _InputIterator , typename _Hash =
hash<__iter_key_t<_InputIterator>>, typename _Pred =
equal_to<__iter_key_t<_InputIterator>>, typename _Allocator =
allocator<__iter_to_alloc_t<_InputIterator>>, typename =
_RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_map (_InputIterator,
_InputIterator, typename unordered_map< int, int >::size_type={},
_Hash=_Hash(), _Pred=_Pred(), _Allocator=_Allocator()) ->
unordered_map< __iter_key_t< _InputIterator >, __iter_val_t<
_InputIterator >, _Hash, _Pred, _Allocator >
this is the big one β the fully defaulted guide, the one that lets you go unordered_map(first, last) with literally nothing else and it just works β¨ note the size_type={} default (empty braces, cute), the _Hash=_Hash(), _Pred=_Pred(), _Allocator=_Allocator() defaults, and __iter_to_alloc_t<_InputIterator> doing the allocator-type extraction. three separate _Require... gatekeepers on this one, it's locked down π₯
template<typename _Key , typename _Tp , typename _Allocator , typename
= _RequireAllocator<_Allocator>> unordered_map (initializer_list<
pair< _Key, _Tp > >, _Allocator) -> unordered_map< _Key, _Tp, hash<
_Key >, equal_to< _Key >, _Allocator >
template<typename _Key , typename _Tp , typename _Allocator , typename
= _RequireAllocator<_Allocator>> unordered_map (initializer_list<
pair< _Key, _Tp > >, typename unordered_map< int, int >::size_type,
_Allocator) -> unordered_map< _Key, _Tp, hash< _Key >, equal_to<
_Key >, _Allocator >
template<typename _Key , typename _Tp , typename _Hash , typename
_Allocator , typename = _RequireNotAllocatorOrIntegral<_Hash>,
typename = _RequireAllocator<_Allocator>> unordered_map
(initializer_list< pair< _Key, _Tp > >, typename unordered_map< int,
int >::size_type, _Hash, _Allocator) -> unordered_map< _Key, _Tp,
_Hash, equal_to< _Key >, _Allocator >
the initializer_list family π same energy, but now the key and mapped types come from pair< _Key, _Tp > instead of iterators. hash< _Key > and equal_to< _Key > are the fallbacks, and once again that unordered_map< int, int >::size_type shows up for the bucket count π
template<typename _Key , typename _Tp , typename _Hash = hash<_Key>,
typename _Pred = equal_to<_Key>, typename _Allocator =
allocator<pair<const _Key, _Tp>>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_map (initializer_list<
pair< _Key, _Tp > >, typename unordered_map< int, int
>::size_type={}, _Hash=_Hash(), _Pred=_Pred(),
_Allocator=_Allocator()) -> unordered_map< _Key, _Tp, _Hash, _Pred,
_Allocator >
and the fully-defaulted initializer_list one π«Ά note the allocator default is allocator<pair<const _Key, _Tp>> β with a const on the key, because map keys don't change, periodt π
now unordered_multimap, and it's the exact same eight-ish shapes, just with the multi-container name everywhere. iykyk the drill by now π
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> unordered_multimap (_InputIterator,
_InputIterator, _Allocator) -> unordered_multimap< __iter_key_t<
_InputIterator >, __iter_val_t< _InputIterator >, hash<
__iter_key_t< _InputIterator > >, equal_to< __iter_key_t<
_InputIterator > >, _Allocator >
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> unordered_multimap (_InputIterator,
_InputIterator, unordered_multimap< int, int >::size_type,
_Allocator) -> unordered_multimap< __iter_key_t< _InputIterator >,
__iter_val_t< _InputIterator >, hash< __iter_key_t< _InputIterator >
>, equal_to< __iter_key_t< _InputIterator > >, _Allocator >
template<typename _InputIterator , typename _Hash , typename _Allocator
, typename = _RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireAllocator<_Allocator>> unordered_multimap (_InputIterator,
_InputIterator, unordered_multimap< int, int >::size_type, _Hash,
_Allocator) -> unordered_multimap< __iter_key_t< _InputIterator >,
__iter_val_t< _InputIterator >, _Hash, equal_to< __iter_key_t<
_InputIterator > >, _Allocator >
careful β the multimap versions write unordered_multimap< int, int >::size_type without a leading typename in the parameter list on these ones (the map ones had it). keep that in mind if you're ever cross-referencing, because I'm copying it exactly, not fixing it πΈ
template<typename _InputIterator , typename _Hash =
hash<__iter_key_t<_InputIterator>>, typename _Pred =
equal_to<__iter_key_t<_InputIterator>>, typename _Allocator =
allocator<__iter_to_alloc_t<_InputIterator>>, typename =
_RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_multimap (_InputIterator,
_InputIterator, unordered_multimap< int, int >::size_type={},
_Hash=_Hash(), _Pred=_Pred(), _Allocator=_Allocator()) ->
unordered_multimap< __iter_key_t< _InputIterator >, __iter_val_t<
_InputIterator >, _Hash, _Pred, _Allocator >
template<typename _Key , typename _Tp , typename _Allocator , typename
= _RequireAllocator<_Allocator>> unordered_multimap
(initializer_list< pair< _Key, _Tp > >, _Allocator) ->
unordered_multimap< _Key, _Tp, hash< _Key >, equal_to< _Key >,
_Allocator >
template<typename _Key , typename _Tp , typename _Allocator , typename
= _RequireAllocator<_Allocator>> unordered_multimap
(initializer_list< pair< _Key, _Tp > >, unordered_multimap< int, int
>::size_type, _Allocator) -> unordered_multimap< _Key, _Tp, hash<
_Key >, equal_to< _Key >, _Allocator >
template<typename _Key , typename _Tp , typename _Hash , typename
_Allocator , typename = _RequireNotAllocatorOrIntegral<_Hash>,
typename = _RequireAllocator<_Allocator>> unordered_multimap
(initializer_list< pair< _Key, _Tp > >, unordered_multimap< int, int
>::size_type, _Hash, _Allocator) -> unordered_multimap< _Key, _Tp,
_Hash, equal_to< _Key >, _Allocator >
okay and here's where the page just stops mid-thought π the last one is literally still being typed out:
template<typename _Key , typename _Tp , typename _Hash = hash<_Key>,
typename _Pred = equal_to<_Key>, typename _Allocator =
allocator<pair<const _Key, _Tp>>, typename =
β¦and that's genuinely where it cuts off, bestie, mid-typename, no closing bracket, nothing. so if you were waiting for the fully-defaulted unordered_multimap initializer_list guide β yeah, it's coming, keep scrolling ππ«Ά
β¦and the deduction guides literally just keep going, bestie. No cap, we're still in the same list β deep breath, hydrate, we got this π
unordered_multimap, theinitializer_listone with the defaulted bucket count plus hash/pred/allocator (yes, this is the tail end of a signature that started before this bit):
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_multimap (initializer_list<
pair< _Key, _Tp > >, unordered_multimap< int, int >::size_type={},
_Hash=_Hash(), _Pred=_Pred(), _Allocator=_Allocator()) ->
unordered_multimap< _Key, _Tp, _Hash, _Pred, _Allocator >
unordered_multiset, iterator range + allocator, with the value type and friends pulled out ofiterator_traits:
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> unordered_multiset (_InputIterator,
_InputIterator, unordered_multiset< int >::size_type, _Allocator) ->
unordered_multiset< typename iterator_traits< _InputIterator
>::value_type, hash< typename iterator_traits< _InputIterator
>::value_type >, equal_to< typename iterator_traits< _InputIterator
>::value_type >, _Allocator >
unordered_multiset, iterator range + hash + allocator, and the comparator gets deduced as the defaultequal_toof the value type:
template<typename _InputIterator , typename _Hash , typename _Allocator
, typename = _RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireAllocator<_Allocator>> unordered_multiset (_InputIterator,
_InputIterator, unordered_multiset< int >::size_type, _Hash,
_Allocator) -> unordered_multiset< typename iterator_traits<
_InputIterator >::value_type, _Hash, equal_to< typename
iterator_traits< _InputIterator >::value_type >, _Allocator >
unordered_multiset, iterator range, with hash, pred and allocator all defaulted offiterator_traits:
template<typename _InputIterator , typename _Hash = hash<typename
iterator_traits<_InputIterator>::value_type>, typename _Pred =
equal_to<typename iterator_traits<_InputIterator>::value_type>,
typename _Allocator = allocator<typename
iterator_traits<_InputIterator>::value_type>, typename =
_RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_multiset (_InputIterator,
_InputIterator, unordered_multiset< int >::size_type={},
_Hash=_Hash(), _Pred=_Pred(), _Allocator=_Allocator()) ->
unordered_multiset< typename iterator_traits< _InputIterator
>::value_type, _Hash, _Pred, _Allocator >
unordered_multiset, theinitializer_list+ allocator glow-up:
template<typename _Tp , typename _Allocator , typename =
_RequireAllocator<_Allocator>> unordered_multiset (initializer_list<
_Tp >, unordered_multiset< int >::size_type, _Allocator) ->
unordered_multiset< _Tp, hash< _Tp >, equal_to< _Tp >, _Allocator >
unordered_multiset,initializer_list+ hash + allocator:
template<typename _Tp , typename _Hash , typename _Allocator , typename
= _RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireAllocator<_Allocator>> unordered_multiset (initializer_list<
_Tp >, unordered_multiset< int >::size_type, _Hash, _Allocator) ->
unordered_multiset< _Tp, _Hash, equal_to< _Tp >, _Allocator >
unordered_multiset, theinitializer_listone with every single parameter defaulted β she's giving full-service:
template<typename _Tp , typename _Hash = hash<_Tp>, typename _Pred =
equal_to<_Tp>, typename _Allocator = allocator<_Tp>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_multiset (initializer_list<
_Tp >, unordered_multiset< int >::size_type={}, _Hash=_Hash(),
_Pred=_Pred(), _Allocator=_Allocator()) -> unordered_multiset< _Tp,
_Hash, _Pred, _Allocator >
unordered_set, iterator range + allocator (note the bucket-count parameter here has no default, unlike her later sisters):
template<typename _InputIterator , typename _Allocator , typename =
_RequireInputIter<_InputIterator>, typename =
_RequireAllocator<_Allocator>> unordered_set (_InputIterator,
_InputIterator, unordered_set< int >::size_type, _Allocator) ->
unordered_set< typename iterator_traits< _InputIterator
>::value_type, hash< typename iterator_traits< _InputIterator
>::value_type >, equal_to< typename iterator_traits< _InputIterator
>::value_type >, _Allocator >
unordered_set, iterator range + hash + allocator:
template<typename _InputIterator , typename _Hash , typename _Allocator
, typename = _RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireAllocator<_Allocator>> unordered_set (_InputIterator,
_InputIterator, unordered_set< int >::size_type, _Hash, _Allocator)
-> unordered_set< typename iterator_traits< _InputIterator
>::value_type, _Hash, equal_to< typename iterator_traits<
_InputIterator >::value_type >, _Allocator >
unordered_set, iterator range with hash, pred and allocator all defaulted:
template<typename _InputIterator , typename _Hash = hash<typename
iterator_traits<_InputIterator>::value_type>, typename _Pred =
equal_to<typename iterator_traits<_InputIterator>::value_type>,
typename _Allocator = allocator<typename
iterator_traits<_InputIterator>::value_type>, typename =
_RequireInputIter<_InputIterator>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_set (_InputIterator,
_InputIterator, unordered_set< int >::size_type={}, _Hash=_Hash(),
_Pred=_Pred(), _Allocator=_Allocator()) -> unordered_set< typename
iterator_traits< _InputIterator >::value_type, _Hash, _Pred,
_Allocator >
unordered_set,initializer_list+ allocator:
template<typename _Tp , typename _Allocator , typename =
_RequireAllocator<_Allocator>> unordered_set (initializer_list< _Tp
>, unordered_set< int >::size_type, _Allocator) -> unordered_set<
_Tp, hash< _Tp >, equal_to< _Tp >, _Allocator >
unordered_set,initializer_list+ hash + allocator:
template<typename _Tp , typename _Hash , typename _Allocator , typename
= _RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireAllocator<_Allocator>> unordered_set (initializer_list< _Tp
>, unordered_set< int >::size_type, _Hash, _Allocator) ->
unordered_set< _Tp, _Hash, equal_to< _Tp >, _Allocator >
unordered_set, the all-defaultsinitializer_listfinale of the set family:
template<typename _Tp , typename _Hash = hash<_Tp>, typename _Pred =
equal_to<_Tp>, typename _Allocator = allocator<_Tp>, typename =
_RequireNotAllocatorOrIntegral<_Hash>, typename =
_RequireNotAllocator<_Pred>, typename =
_RequireAllocator<_Allocator>> unordered_set (initializer_list< _Tp
>, unordered_set< int >::size_type={}, _Hash=_Hash(), _Pred=_Pred(),
_Allocator=_Allocator()) -> unordered_set< _Tp, _Hash, _Pred,
_Allocator >
vector, built from an iterator range, value type and allocator both defaulted:
template<typename _InputIterator , typename _ValT = typename
iterator_traits<_InputIterator>::value_type, typename _Allocator =
allocator<_ValT>, typename = _RequireInputIter<_InputIterator>,
typename = _RequireAllocator<_Allocator>> vector (_InputIterator,
_InputIterator, _Allocator=_Allocator()) -> vector< _ValT,
_Allocator >
vector, the(size_t, _Tp, _Allocator)one β count, value, allocator:
template<typename _Tp , typename _Allocator = allocator<_Tp>, typename
= _RequireAllocator<_Allocator>> vector (size_t, _Tp,
_Allocator=_Allocator()) -> vector< _Tp, _Allocator >
And that's the whole list, bestie β we made it, nobody fainted π
β¨ Detailed Description β¨
GNU debug code, replaces standard behavior with debug behavior. That's the whole vibe of this namespace, honestly.
So here's the tea about the macros and namespaces used by the implementation outside of the debug wrappers β they exist to verify certain properties. The __glibcxx_requires_xxx macros are merely wrappers around the __glibcxx_check_xxx wrappers when we are compiling with debug mode. But β and this is the important part, don't skip it β they disappear when we are in release mode, so that there is no checking performed in, e.g., the standard library algorithms. Zero. Nada. She's gone π
Fr fr: debug mode on = checks happen. Release mode = the requires-macros vanish and nothing gets checked in places like the standard library algorithms. Don't be surprised, that's literally by design π
πΈ Function Documentation πΈ
π¦ template<typename _Tp , typename _Alloc > void std::__debug::swap (forward_list< _Tp, _Alloc > & __lx, forward_list< _Tp, _Alloc > & __ly) β [inline], [protected], [noexcept]
The signature in full:
template<typename _Tp , typename _Alloc > void std::__debug::swap
(forward_list< _Tp, _Alloc > & __lx, forward_list< _Tp, _Alloc > & __ly)
[inline], [protected], [noexcept]
It's the debug-flavoured swap for two forward_lists, __lx and __ly, and it's marked [inline], [protected] and [noexcept].
See std::forward_list::swap(). π
π Author π
Generated automatically by Doxygen for libstdc++ from the source code. So nobody hand-wrote this bad boy β Doxygen did it for libstdc++ straight from the source β¨
And that's a wrap on std::__debug(3cxx), bestie β brought to you by libstdc++ and its source code, with the Doxygen-generated lore intact. Go forth and compile with debug mode on, mwah π
π
π¦ where this page comes from
- ubuntu noble: libstdc++-14-doc 14-20240412-0ubuntu1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms