1

I am trying to pass a callback function as function parameter. But getting template substitution failure errors in following code. Not sure why template substitution is failing.

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

And error is as following

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);
g-217
  • 2,069
  • 18
  • 33

1 Answers1

11

The compiler can't both cast to a std::function and deduce the template arguments. It doesn't understand the mapping between an arbitrary function pointer and a std::function.

There are a few ways round this.

You could explicitly create a std::function at the call site:

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

You could write a make_function function to deduce the types for you. You can find discussions and implementations of this online, such as here, here and here.

myfun(gg,make_function(fun));

You could just forget about std::function and deduce the entire function type. This is the approach I would take:

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;
}
Community
  • 1
  • 1
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • 1
    When you say the compiler can't both do the cast and the deduction, are you saying that it's against the rules or just that the compiler isn't bright enough to do it? – Daniel McLaury Jun 03 '20 at 16:00