Search code examples
c++c++11templatestypestemplate-argument-deduction

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?


Solution

  • The problem for the compiler is to decide which of your parameters to use for the type deduction. If you help the compile by breaking the possible deduction from the second parameter and force it to use the first, it works as expected:

    template<typename T> struct identity { using type = T; };
    
    template<class CharType>
    void f1(CharType* str, typename identity<function<bool(CharType)>>::type fn_filter)
    {}
    

    Live example