Page 7 - HRM-00-v1
P. 7

T EMPLATE TYPE DEDUCTION IS AN
YOUR WAY BY NOT DOING WHAT YOU WANT.BASED ON AN EXAMPLE OF A FUNCTION THAT CHANGES THE KEYS
OF THE ELEMENTS OF AN STD::MAP, WE SEE HOW TO PREVENT TEMPLATE TYPE DEDUCTION TO KICK IN
FOR SELECTED FUNCTION PARAMETERS.
MOTIVATING EXAMPLE: CHANGING THE KEYS OF A MAP OR SET
Here is how to change a key of the elements of a std::map:
auto myMap = std::map<std::string, int>{ {“one”, 1}, {“two”, 2}, {“three”, 3} };
At first sight, this looks really simple because std::map and std::set seem to have the same code to extract a node and to put it back in. So we could have a generic function that takes a template parameter type for the container and be done with it.
Except they don’t have the same code. They almost have the same code, except for the method to change the value of the extracted node. If you look at line 6 in both of the above snippets, you’ll see that the one for std::map uses node.key() and the one for std::set uses node.value(). This difference can be surprising, especially since the values of sets are often themselves called “keys” as in key_type, which is an alias for value_type in std::set.
So we need to have two implementations for replace_key.
One way out of this issue is to call the function replace_value for std::set. Then we’d have two independent functions with two im- plementations. Until we decide to implement replace_value for std::vectors too, and we’re back to the need of having two overloads of a function that has different code for different containers.
In any case, I think it is interesting to see how to overload the func- tion for several containers, because it is not trivial. In particular, it shows us how to deactivate the template type deduction of selected function parameters.
The Problem of Template Type Deduction
What’s all that fuss with overloading anyway? Let’s just write the overloads like this:
template<typename Key, typename Value>
void replace_key(std::map<Key, Value>& container, // this is the overload for
maps
const Key& oldKey, const Key& newKey)
{
auto node = container.extract(oldKey); if(!node.empty())
{
node.key() = newKey;
container.insert(std::move(node)); }
}
template<typename Key>
void replace_key(std::set<Key>& container, // this is the overload for sets
const Key& oldKey, const Key& newKey)
{
auto node = container.extract(oldKey); if(!node.empty())
{
node.value() = newKey;
container.insert(std::move(node)); }
}
 LANGUAGE FEATURES
 How to Avoid Template Type Deduction in C++
 AWESOME FEATURE OF C++. EXCEPT WHEN IT GETS IN
    auto node = myMap.extract(“two”); if (!node.empty())
{
node.key() = “dos”;
myMap.insert(std::move(node)); }
This relies on the C++17 extract method of std::map.
And std::set has a similar way to perform the operation:
auto mySet = std::set<std::string>{“one”, “two”, “three”};
auto node = mySet.extract(“two”); if(!node.empty())
{
node.value() = “dos”;
mySet.insert(std::move(node)); }
                              But you don’t want to write all this in your code. It would be nicer to have a function that encapsulates the mechanics of taking a node off the container and putting it back in, like this:
auto myMap = std::map<std::string, int>{ {“one”, 1}, {“two”, 2}, {“three”, 3} }; replace_key(myMap, “two”, “dos”);
           auto mySet = std::set<std::string>{“one”, “two”, “three”}; replace_key(mySet, “two”, «dos”);
   September 2019 | 7
 















































   5   6   7   8   9