如何将std :: map转换为std :: function?

时间:2018-05-28 11:10:13

标签: c++ c++11 templates lambda stl

std::map<K,V>实现std::function<V(K)>类型的部分函数。

我正在尝试实现一个将map2fun()转换为std::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];
    };
}

我的问题是:

  • STL for C ++ 11中是否有类似的功能?
  • 如果没有,我怎样才能用C ++ 11实现它?

1 个答案:

答案 0 :(得分:4)

  

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

不,据我所知。

std::map本身就是&#34; STL for C ++ 11&#34;中可用的类似功能。 (以及C ++ 98),恕我直言。

  

如果没有,我怎样才能用C ++ 11实现它?

通过示例

为代码添加一些typename
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开始,简化如下

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),这给出了一个非常难看的错误消息(不是简单的&#34) ; map2fun()未实现)。

如果C容器定义mapped_type类型,则可以使用SFINAE避免此问题,仅启用此功能(通过示例);我的意思是

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;
 }