deductiongu...ordered_map(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸŽ€ NAME πŸŽ€

okay so the raw NAME line is literally deductionguidesforstd::unordered_map - deductionguidesforstd::unordered_map β€” yes, it says it twice, iconic behavior. This is the deductiongu...ordered_map(3) page from the C++ Standard Libary manual, and it’s all about the deduction guides for std::unordered_map. bestie, it’s giving template magic with main-character energy. πŸ’…βœ¨


✨ Synopsis ✨

Defined in header <unordered_map> πŸ¦‹

(1) β€” since C++17

template< class InputIt,
          class Hash = std::hash<iter_key_t<InputIt>>,
          class Pred = std::equal_to<iter_key_t<InputIt>>,
          class Alloc = std::allocator<iter_to_alloc_t<InputIt>> >
unordered_map( InputIt, InputIt,
               typename /*see below*/::size_type = /*see below*/,
               Hash = Hash(), Pred = Pred(), Alloc = Alloc()
           )
    -> unordered_map<iter_key_t<InputIt>,
                     iter_val_t<InputIt>,
                     Hash, Pred, Alloc>;

(2) β€” since C++17

template< class Key, class T, class Hash = std::hash<Key>,
          class Pred = std::equal_to<Key>,
          class Alloc = std::allocator<std::pair<const Key, T>> >
unordered_map( std::initializer_list<std::pair<Key, T>>,
               typename /*see below*/::size_type = /*see below*/,
               Hash = Hash(), Pred = Pred(), Alloc = Alloc()
           )
    -> unordered_map<Key, T, Hash, Pred, Alloc>;

(3) β€” since C++17

template< class InputIt, class Alloc >
unordered_map( InputIt, InputIt, typename /*see below*/::size_type, Alloc )
    -> unordered_map<iter_key_t<InputIt>,
                     iter_val_t<InputIt>,
                     std::hash<iter_key_t<InputIt>>,
                     std::equal_to<iter_key_t<InputIt>>,
                     Alloc>;

(4) β€” since C++17

template< class InputIt, class Alloc >
unordered_map( InputIt, InputIt, Alloc )
    -> unordered_map<iter_key_t<InputIt>,
                     iter_val_t<InputIt>,
                     std::hash<iter_key_t<InputIt>>,
                     std::equal_to<iter_key_t<InputIt>>,
                     Alloc>;

(5) β€” since C++17

template< class InputIt, class Hash, class Alloc >
unordered_map( InputIt, InputIt, typename /*see below*/::size_type, Hash, Alloc )
    -> unordered_map<iter_key_t<InputIt>,
                     iter_val_t<InputIt>, Hash,
                     std::equal_to<iter_key_t<InputIt>>,
                     Alloc>;

(6) β€” since C++17

template< class Key, class T, typename Alloc >
unordered_map( std::initializer_list<std::pair<Key, T>>,
               typename /*see below*/::size_type, Alloc )
    -> unordered_map<Key, T, std::hash<Key>,
                     std::equal_to<Key>, Alloc>;

(7) β€” since C++17

template< class Key, class T, typename Alloc >
unordered_map( std::initializer_list<std::pair<Key, T>>,
               Alloc )
    -> unordered_map<Key, T, std::hash<Key>,
                     std::equal_to<Key>, Alloc>;

(8) β€” since C++17

template< class Key, class T, class Hash, class Alloc >
unordered_map( std::initializer_list<std::pair<Key, T>>,
               typename /*see below*/::size_type, Hash, Alloc )
    -> unordered_map<Key, T, Hash, std::equal_to<Key>,
                     Alloc>;

(9) β€” since C++23

template< ranges::input_range R,
          class Hash = std::hash<range_key_t<R>>,
          class Pred = std::equal_to<range_key_t<R>>,
          class Alloc = std::allocator<range_to_alloc_t<R>> >
unordered_map( std::from_range_t, R&&,
               typename /* see description */::size_type = /* see description */,
               Hash = Hash(), Pred = Pred(), Alloc = Alloc()
           )
    -> unordered_map<range_key_t<R>, range_mapped_t<R>,
                     Hash, Pred, Alloc>;

(10) β€” since C++23

template< ranges::input_range R, class Alloc >
unordered_map( std::from_range_t, R&&,
               typename /* see description */::size_type, Alloc )
    -> unordered_map<range_key_t<R>, range_mapped_t<R>,
                     std::hash<range_key_t<R>>,
                     std::equal_to<range_key_t<R>>, Alloc>;

(11) β€” since C++23

template< ranges::input_range R, class Alloc >
unordered_map( std::from_range_t, R&&, Alloc )
    -> unordered_map<range_key_t<R>, range_mapped_t<R>,
                     std::hash<range_key_t<R>>,
                     std::equal_to<range_key_t<R>>, Alloc>;

(12) β€” since C++23

template< ranges::input_range R, class Hash, class Alloc >
unordered_map( std::from_range_t, R&&, typename /* see description */::size_type,
               Hash, Alloc )
    -> unordered_map<range_key_t<R>, range_mapped_t<R>, Hash,
                     std::equal_to<range_key_t<R>>, Alloc>;

Exposition-only helper type aliases

iter_val_t <span>β€”</span> (exposition only*)

template< class InputIter >
using iter_val_t =
    typename std::iterator_traits<InputIter>::value_type;

iter_key_t <span>β€”</span> (exposition only*)

template< class InputIter >
using iter_key_t =
    std::remove_const_t< std::tuple_element_t<0, iter_val_t<InputIter>>>;

iter_mapped_t <span>β€”</span> (exposition only*)

template< class InputIter >
using iter_mapped_t =
    std::tuple_element_t<1, iter_val_t<InputIter>>;

iter_to_alloc_t <span>β€”</span> (exposition only*)

template< class InputIter >
using iter_to_alloc_t =
    std::pair<std::add_const_t<tuple_element_t<0, iter_val_t<InputIter>>>,
              std::tuple_element_t<1, iter_val_t<InputIter>>>;

range_key_t <span>β€”</span> (since C++23) (exposition only*)

template< ranges::input_range Range >
using range_key_t =
    std::remove_const_t<typename ranges::range_value_t<Range>::first_type>;

range_mapped_t <span>β€”</span> (since C++23) (exposition only*)

template< ranges::input_range Range >
using range_mapped_t =
    typename ranges::range_value_t<Range>::second_type;

range_to_alloc_t <span>β€”</span> (since C++23) (exposition only*)

template< ranges::input_range Range >
using range_to_alloc_t =
    std::pair<std::add_const_t<typename ranges::range_value_t<Range>::first_type>,
              typename ranges::range_value_t<Range>::second_type>;

1-8) These deduction guides are provided for unordered_map to allow deduction from an iterator range (overloads (1,3-5)) and std::initializer_list (overloads (2,6-8)). slay πŸŽ€

9-12) These deduction guides are provided for unordered_map to allow deduction from a std::from_range_t tag and an input_range. highkey very C++23 of them. πŸ¦‹

These overloads participate in overload resolution only if InputIt satisfies LegacyInputIterator, Alloc satisfies Allocator, neither Hash nor Pred satisfy Allocator, and Hash is not an integral type. heads up, that’s the whole vibe check. πŸ’…

Note: the extent to which the library determines that a type does not satisfy LegacyInputIterator is unspecified, except that as a minimum integral types do not qualify as input iterators. Likewise, the extent to which it determines that a type does not satisfy Allocator is unspecified, except that as a minimum the member type Alloc::value_type must exist and the expression std::declval<Alloc&>().allocate(std::size_t{}) must be well-formed when treated as an unevaluated operand. no cap, that’s literally the fine print. 😭

The size_type parameter type in these guides refers to the size_type member type of the type deduced by the deduction guide. iykyk ✨


🌸 Notes 🌸

  • __cpp_lib_containers_ranges β€” value 202202L, standard (C++23), feature: β€œRanges-aware construction and insertion; overloads (9-12)”. periodt πŸ’–

πŸ’– Example πŸ’–

// Run this code

#include <unordered_map>

int main()
{
    // std::unordered_map m1 = {{"foo", 1}, {"bar", 2}};
        // Error: braced-init-list has no type cannot
        // deduce pair<Key, T> from {"foo", 1} or {"bar", 2}

    std::unordered_map m1 = {std::pair{"foo", 2}, {"bar", 3}}; // guide #2
    std::unordered_map m2(m1.begin(), m1.end()); // guide #1
}

not me rereading the comment that says braced-init-list has no type cannot β€” bestie, it’s exactly as published, and it’s still giving useful. 🫢


πŸ¦‹ Defect reports πŸ¦‹

The following behavior-changing defect reports were applied retroactively to previously published C++ standards. slay for retroactive fixes. πŸ’€

  • LWG 3025 β€” applied to C++17. Behavior as published: initializer-list guides take std::pair<const Key, T>. Correct behavior: use std::pair<Key, T>. literally the glow-up. ✨

source: http://cppreference.com Β· date/version: 2024.06.10 Β· page: deductiongu...ordered_map(3) β€” bye bestie, go deduce something cute πŸ’–πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from