Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::map transformer template

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;
}
like image 364
sebastian Avatar asked Feb 21 '26 19:02

sebastian


1 Answers

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;
}
like image 97
super Avatar answered Feb 23 '26 07:02

super