Why does this not work (in C++11) and how can I fix it:
#include <iostream>
#include <functional>
using namespace std;
template <typename T>
int apply(string x, const function<int(T)>& fn)
{
T t = { x };
return fn(t);
}
struct S {
string data;
};
int process_s(const S& s)
{
return s.data.size();
}
int main()
{
cout << apply("abc", process_s);
}
The error is
prog.cc:21:8: error: no matching function for call to 'apply'
cout<<apply("abc", process_s);
^~~~~
prog.cc:7:5: note: candidate template ignored:
could not match 'function<int (type-parameter-0-0)>'
against 'int (const S &)'
int apply(string x, const function<int(T)>& fn) {
^
1 error generated.
I tried the approach from here , but it doesn't work either:
#include <iostream>
#include <functional>
using namespace std;
template <typename T>
struct id {
typedef T type;
};
template <typename T>
using nondeduced = typename id<T>::type;
template <typename T>
int apply(string x, const function<nondeduced<int(T)> >& fn)
{
T t = { x };
return fn(t);
}
struct S {
string data;
};
int process_s(const S& s)
{
return s.data.size();
}
int main()
{
cout << apply("abc", process_s);
}
The second approach only works when there's another way to deduce T
. Your use case has no other function parameter which can be used for that deduction.
The deduction fails in your original attempt because a function pointer/reference ( process_s
) is not a std::function
. Implicit conversion won't count, it has to be an object whose type is a std::function
instantiation for the deduction to succeed.
Assuming there's no option to add any more parameters to the function, you are left with two options:
apply<S>(...)
. std::function
object and pass it to your first attempt, as the second function argument. The second choice can be less ugly in C++17 since there are now deduction guides available. So the invocation can in fact become apply("abc", std::function{process_s});
As @StoryTeller states, an implicit conversion does not count.
The other option that can be considered is, giving up on using std::function
. Then it will put you in the right place to start compiling at:
template <typename T>
int apply(string x, int(&fn)(T))
{
T t = { x };
return fn(t);
}
Not to mention that you can avoid the overhead of std::function
as well.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.