首页 > 解决方案 > 如何将 std::map 转换为 std::function?

问题描述

Astd::map<K,V>实现了type 的部分函数std::function<V(K)>

我正在尝试实现一个map2fun()将 astd::map转换为std::function对象的通用函数。

以下不编译:

template<typename M>
function<M::mapped_type(M::key_type)> map2fun(M& m)
{
  return [&m](M::key_type k)
    {
      return m[k];
    };
}

我的问题是:

标签: c++c++11templateslambdastl

解决方案


C++11 的 STL 中是否有类似的功能可用?

不,据我所知。

但它std::map本身是“在 C++11 的 STL 中可用的类似功能”(以及 C++98),恕我直言。

如果没有,我如何用 C++11 实现它?

例如,将一些typename's 添加到您的代码中

template <typename M>
std::function<typename M::mapped_type(typename M::key_type)> map2fun (M & m)
 { return [&m](typename M::key_type k) { return m[k]; }; }

但我发现这样更清楚

template <typename K, typename V>
std::function<V(K)> m2f2 (std::map<K, V> & m)
 { return [&m](K k) { return m[k]; }; }

但是,正如 Jarod42 所指出的(谢谢!),这个拦截std::map只(不是std::unordered_map,不是类似的(也是自定义的)类型),所以你可以使它更灵活如下

template <template <typename ...> class C, typename K, typename V,
          typename ... Ts>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
 { return [&m](K k) { return m[k]; }; }

并且,从 C++17 开始,将 con 简化如下

template <template <typename ...> class C, typename K, typename V>
std::function<V(K)> m2f2 (C<K, V> & m)
 { return [&m](K k) { return m[k]; }; }

作为 Jarod42 的指针(再次感谢!),此模板模板版本也可用于其他容器(std::vector例如),这会给出一个非常丑陋的错误消息(不是简单明了的“map2fun() 未实现”)。

您可以使用 SFINAE 避免此问题,仅在C容器定义mapped_type类型时启用该功能(通过示例);我是说

template <template <typename ...> class C, typename K, typename V,
          typename ... Ts, typename = typename C<K, V, Ts...>::mapped_type>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
 { return [&m](K k) { return m[k]; }; }

但现在我更简单的版本比你原来的更复杂:(。

以下是一个完整的工作双重示例

#include <map>
#include <iostream>
#include <functional>
#include <unordered_map>

template <typename M>
std::function<typename M::mapped_type(typename M::key_type)> m2f1 (M & m)
 { return [&m](typename M::key_type k) { return m[k]; }; }

template <template <typename ...> class C, typename K, typename V,
          typename ... Ts, typename = typename C<K, V, Ts...>::mapped_type>
std::function<V(K)> m2f2 (C<K, V, Ts...> & m)
 { return [&m](K k) { return m[k]; }; }

int main ()
 {
   std::map<int, long> m1 {{0, 1L}, {1, 2L}, {2, 4L}, {3, 8L}};
   std::unordered_map<int, long> m2 {{0, 1L}, {1, 2L}, {2, 4L}, {3, 8L}};

   auto l1 { m2f1(m1) };
   auto l2 { m2f2(m2) };
   auto l3 { m2f1(m1) };
   auto l4 { m2f2(m2) };

   std::cout << l1(2) << std::endl;
   std::cout << l2(2) << std::endl;
   std::cout << l3(2) << std::endl;
   std::cout << l4(2) << std::endl;
 }

推荐阅读