Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::function with templates

So in it's most distilled form I have something like this going on,

template <class T>
bool f(const T &a, const T &b, std::function<bool(const T&, const T&)> func)
{
    return func(a,b);
}

template <class T>
bool g(const T &a, const T &b)
{
    return true;
}  

But any attempt to call f(), with anything, f('a', 'b', g), f(1, 2, g), always results in "no matching function for call to 'f'", regardless of whether I pass the variables as const references or just plain values or whatever. I'm assuming it's failing to deduce some template, but I have no idea where or why.

I will admit, I have a very tenuous grasp on how to use function objects in general, is doing something like this even possible?

like image 362
Arii Avatar asked Sep 26 '18 01:09

Arii


2 Answers

The parameter func is declared as std::function, and you're trying to pass a function pointer, which requires implicit conversion. Template argument deduction doesn't consider implicit conversion and then deduction fails.

Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.

You can construct an std::function explicitly,

f('a', 'b', static_cast<std::function<bool(const char&, const char&)>>(g<char>));

Or specify the template argument explicitly (to bypass template argument deduction and make implicit conversion taking effect later),

f<char>('a', 'b', g<char>);    

Or just don't use std::function.

template <class T, class F>
bool f(const T &a, const T &b, F func)
{
    return func(a,b);
}

f('a', 'b', g<char>);
like image 104
songyuanyao Avatar answered Sep 29 '22 07:09

songyuanyao


I've fixed this up a bit for you and added some examples. This should help you to understand how to use a simple std::function.

#include <iostream>
#include <string>
#include <functional>

template <class T>
bool f(const T &a, const T &b, std::function<bool(const T&, const T&)> func)
{
    return func(a,b);
}

template <class T>
bool g(const T &a, const T &b)
{
    return a==b; // a simple comparator
}  

int main()
{
   int a = 1;
   int b = 1;

   // instantiate f and g as integer type functions
   if( f<int>(a,b,g<int>) == true) 
      std::cout << "true" << std::endl;
   else
      std::cout << "false" << std::endl;

   std::string c="dead";
   std::string d="beef";
   // and now as strings
   if( f<std::string>(c,d,g<std::string>) == true) 
      std::cout << "true" << std::endl;
   else
      std::cout << "false" << std::endl;
   return 0;
}
like image 45
Matthew Fisher Avatar answered Sep 29 '22 06:09

Matthew Fisher