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

将lamdas与模板函数一起使用时出现错误C2672和C2784

  •  0
  • a a  · 技术社区  · 3 年前

    我已经编写了以下函数,它在迭代二维向量时隐藏循环:

        template<typename ElementType>
        void iterateOver2DVector(std::vector<std::vector<ElementType>> & vec, 
                                 std::function<void(ElementType & element)> function)
        {
            for(auto & row : vec)
            {
                for(auto & element : row)
                {
                    function(element);
                }
            }
        }
    

    但我得到了错误:

    'function': no matching overloaded function found
    

    'declaration' : could not deduce template argument for 'type' from 'type'
    

    当它与Lambda一起使用时,如下所示:

    iterateOver2DVector(graph, [](Node & node) { node.update(); } );
    

    有人知道我做错了什么吗?

    0 回复  |  直到 3 年前
        1
  •  1
  •   user17732522    3 年前

    呼叫将尝试推断 ElementType 来自第一和第二参数/自变量对。

    由于函数的第二个参数不是 std::function ,但属于闭合类型。

    如果其中一对失败,那么整个推导也会失败,即使另一对会推导的模板参数 ElementType 正确地

    你的函数不需要推导 ElementType 从第二个参数/自变量对,这样您就可以 非推导上下文 ,因此不会尝试对其进行推导。

    一种常见的方法是使用 std::type_identity_t :

    template<typename ElementType>
    void iterateOver2DVector(std::vector<std::vector<ElementType>> & vec, 
                             std::type_identity_t<std::function<void(ElementType & element)>> function)
    

    std::type_identity_t<T> 是的别名 std::type_identity<T>::type 是的别名 T ,但是由于类型 T 现在是剩下的 :: 它是在一个非推导的上下文中。

    std::type_identity_t 仅在C++20之后可用,但在以前的C++版本中可以轻松定义:

    template<typename T> struct type_identity { using type = T; };
    template<typename T> using type_identity_t = typename type_identity<T>::type;
    

    然而,在这种情况下 std::函数 无论如何都是不必要的开销。只需直接接受闭包类型,而不是 std::函数 :

    template<typename ElementType, typename F>
    void iterateOver2DVector(std::vector<std::vector<ElementType>> & vec, 
                             F function)
    

    A. std::函数 只有当您打算在不依赖于其特定类型的情况下存储可调用项时才有用,例如在类成员中,甚至在这种情况下转换为 std::函数 可以在分配给成员时完成。