Reputation: 2506
The following template for a std::map
transformation function doesn't work. If I use transform_map()
, the compiler cannot deduce the types to find the template. How can it be done?
template <class Key, class FromValue, class ToValue, class Transformer>
std::map<Key, ToValue> transform_map(const std::map<Key, FromValue>& _map,
Transformer _tr) {
std::map<Key, ToValue> res;
std::for_each(_map.cbegin(), _map.cend(),
[&res, &_tr](const std::pair<const Key, FromValue>& kv) {
res[kv.first] = _tr(kv.second);
});
return res;
}
Upvotes: 3
Views: 96
Reputation: 12928
The deduction of a function template is done on the parameters you pass in. Since ToValue
is not related to any of the passed in parameters it can not be deduced.
You can solve this by telling the compiler to default to the value that would be returned if you call Transformer
with a FromValue
.
#include <iostream>
#include <map>
#include <algorithm>
template <class Key, class FromValue, class Transformer, class ToValue = decltype(std::declval<Transformer>()(std::declval<FromValue>()))>
std::map<Key, ToValue> transform_map(const std::map<Key, FromValue>& _map,
Transformer _tr) {
std::map<Key, ToValue> res;
std::for_each(_map.cbegin(), _map.cend(),
[&res, &_tr](const std::pair<const Key, FromValue>& kv) {
res[kv.first] = _tr(kv.second);
});
return res;
}
int main ()
{
std::map<int, double> m1 {{1, 1.5}, {2, 2.5}};
auto m2 = transform_map(m1, [](double d){ return static_cast<int>(d); });
for (auto& p : m1)
std::cout << p.first << " " << p.second << std::endl;
for (auto& p : m2)
std::cout << p.first << " " << p.second << std::endl;
}
Upvotes: 4