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

error C2672 and C2784 when using lamdas with template functions

我编写了以下函数,它在遍历 2d 向量时隐藏了循环:

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

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

该调用将尝试从第一对和第二对 parameter/argument 中推断出 ElementType

第二对将失败,因为函数的第二个参数不是 std::function,而是闭包类型。

如果一对失败,则整个推导失败,即使另一对会正确推导 ElementType 的模板参数。

您的函数不需要从第二对 parameter/argument 推导出 ElementType,因此您可以将其设为 non-deduced 上下文 , 因此不会尝试扣除它。

一个常见的方法是使用 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 的别名,std::type_identity<T>::typeT 的别名,但是由于类型 T 现在是 :: 的左边处于 non-deduced 上下文中。

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::function 只是不必要的开销。直接接受闭包类型,而不是 std::function:

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

A std::function 仅在您打算存储可调用对象而不依赖其特定类型时才有用,例如在 class 成员中,即使在这种情况下,也可以在分配给成员时转换为 std::function