代码之家  ›  专栏  ›  技术社区  ›  ziggystar

如何将STD::映射转换为STD::函数?

  •  3
  • ziggystar  · 技术社区  · 6 年前

    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中是否有类似的功能用于C++ 11?
    • 如果不是,我怎么能用C++ 11实现它呢?
    1 回复  |  直到 6 年前
        1
  •  4
  •   max66    6 年前

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

    不,据我所知。

    但是 std::map 它本身是“在STL中为C++ 11提供的类似功能”(以及C++ 98),IMHO。

    如果不是,我怎么能用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::地图 仅(不 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 例如),这会给出一个非常难看的错误消息(而不是简单明了的“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;
     }