Search code examples
c++c++17structured-bindings

Deduced type in structured binding of unordered_map


I am trying to see the deduced type in structured binding for an unordered_map by using auto, auto & and auto &&.

#include <string>
#include <iostream>
#include <unordered_map>
#include <type_traits>

int main() {   

    std::unordered_map<std::string, std::string> m{{"a","a1"}, {"b","b1"}};

    for(auto &&  [k,v]:m)
    {
        std::cout << std::is_same<decltype(k), std::string const  >::value << '\n';
        std::cout << std::is_same<decltype(v), std::string >::value << '\n';

    }
}

No matter i use for(auto [k,v]:m) or for(auto & [k,v]:m) or for(auto && [k,v]:m), the output is always

1
1

My questions are:

  • why decltype(k) and decltype(v) is not reference type in the case of for(auto & [k,v]:m) or for(auto && [k,v]:m)?

  • why decltype(k) is of type const in the case of for(auto [k,v]:m)?


Solution

  • Question 1) Like specified here

    1) If the argument is an unparenthesized id-expression naming a structured binding, then decltype yields the referenced type (described in the specification of the structured binding declaration).

    and here:

    Case 2: binding a tuple-like type [...] The referenced type for the i-th identifier is std::tuple_element<i, E>::type.

    A std::pair (see answer to question 2) is effectively a tuple of 2. Thus it is 'tuple-like'.

    Thus in this case the base type of Key and T are always returned (yielded).

    Question 2) Internally the unordered_map is allocated as a std::pair<const Key, T>. Hence, the k is const.