October 16th, 2020

Structured binding in C++/WinRT: The key-value pair

Last time, we learned how to add structured binding support to your own types, and noted that the get functions do not have to return references.

C++/WinRT has something similar to a std::pair: The IKeyValuePair<K, V>, which is used to represent a single entry in a map. (C++ uses a std::pair for this.)

Since the kvp.Key() and kvp.Value() methods always return by value, it means that when you use structured binding on an IKeyValuePair, the variables are always copies. The qualifiers on the auto merely describes how the kvp itself is captured.

IKeyValuePair<hstring, int32_t> kvp;
auto& [key, value] = kvp;

This looks like it’s binding key and value as lvalue references, but it’s not. They are non-reference variables. That’s because the code expands to

auto& hidden = kvp;
decltype(auto) key = kvp.Key();
decltype(auto) value = kvp.Value();

Since the results stored into key and value don’t depend on how you bound the source, you may as well bind the hidden variable by reference to avoid an unnecessary copy.

// wasteful copy from kvp to hidden
auto [key, value] = kvp;

// non-copying binding
auto&& [key, value] = kvp;

Bonus chatter: The structured binding of IKeyValuePair comes in particularly handy when you are iterating over something like an IMap:

for (auto&& [key, value] : map)
{
  // use key and value
}
Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Buster C

    Same typo as in Wednesday’s table? Shouldn’t it be:

    auto& hidden = kvp;
    decltype(auto) key = hidden.Key();
    decltype(auto) value = hidden.Value();
    
    • Jeremy Richards

      My best guess, is that the auto& hidden extends the lifetime of kvp in case it is a temporary. Disclaimer: I am no C++ language lawyer and it has been 8 years or so since I used C++ on a daily basis. (Or it could be a typo)

      • anonymous

        this comment has been deleted.