使用std::函数替换模板失败

Template substitution failure with std::function

本文关键字:失败 函数 std 使用 替换      更新时间:2023-10-16

我试图传递回调函数作为函数参数。但是在以下代码中出现模板替换失败错误。不确定为什么模板替换失败。

#include<iostream>
#include <map>
#include <tuple>
#include <functional>
template<typename A,typename B>
void myfun(std::map<A,B> & mm, std::function<std::tuple<A,B>(void)> fn)
{
    A key;
    B val;
    std::tie(key,val) = fn();
    mm[key] = val;
}
std::tuple<std::string,int> fun()
{
    return std::make_tuple(std::string("hi"),1);
}
int main()
{
    std::map<std::string,int> gg;
#if 0
        //fixed version
        std::function<std::tuple<std::string,int>(void)> yy = fun;//fixed
        myfun(gg,yy);//fixed
#else
        // error causing code
        myfun(gg,fun);
#endif
}

错误如下

main.cpp:8:6: note:   template argument deduction/substitution failed:
main.cpp:25:17: note:   mismatched types 'std::function<std::tuple<_T1, _T2>()>' and 'std::tuple<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> (*)()'
     myfun(gg,fun);

编译器不能既强制转换为std::function又推断出模板实参。它不理解任意函数指针和std::function之间的映射。

有几种方法可以绕过这个。

您可以显式地在调用站点创建std::function:

 myfun(gg,std::function<std::tuple<std::string,int>(void)>{fun});`

您可以编写一个make_function函数来为您推断类型。你可以在网上找到关于这个的讨论和实现,比如这里,这里和这里。

myfun(gg,make_function(fun));

您可以忽略std::function并推断整个函数类型。这是我要采取的方法:

template<typename A,typename B, typename Fun>
void myfun(std::map<A,B> & mm, Fun fn)
{
    A key;
    B val;
    std::tie(key,val) = fn();
    mm[key] = val;
}