Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can std::function not accept a deduced type as its template parameter?

#include <functional>

using namespace std;

template<class CharType>
void f1(CharType* str, function<bool(CharType)> fn_filter)
{}

template<class CharType>
void f2(CharType* str, function<bool(char)> fn_filter)
{}

void f3(char* str, char c)
{
    auto fn_filter = [=](char e) -> bool 
    {
        return e == c; 
    };

    f1(str, fn_filter); // error C2784
    f2(str, fn_filter); // OK
}

int main()
{
    f3("ok", 'k');
}

// error C2784: 'void f1(CharType *,std::function<bool(CharType)>)' 
// : could not deduce template argument for 'std::function<bool(CharType)>' 
// from 'f2::<lambda_36be5ecc63077ff97cf3d16d1d5001cb>'

My compiler is VC++ 2013.

Why does f1 not work as expected?

like image 878
xmllmx Avatar asked Dec 16 '22 04:12

xmllmx


1 Answers

The lambda doesn't have type std::function<bool(char)>, it is just some callable object with implementation defined type.

It can be converted to std::function<bool(char)>, but that doesn't help the compiler to deduce the type for the template case. There could for example be lot's of possibilities for CharType for which the lambda can be converted to std::function<bool(CharType)>.

The compiler tries to match the type of the lambda against the parameter of the template function. The lambda has for example a type like lambda_t_1234 and the template parameter is std::function<bool(CharType)>. The types are unrelated and it's not clear what CharType is supposed to be here.

This also isn't special to lambdas or std::function<>. The same happens in all such cases:

template<typename Char>
void f(const std::basic_string<Char> &str) {
}

If you try to call this template function with a char* parameter it won't work, because the connection to the template parameter isn't clear.

like image 95
sth Avatar answered Jan 12 '23 00:01

sth