为什么这不起作用(在C ++ 11中)以及如何解决它:
#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);
}
错误是
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.
我尝试了here的方法,但它也不起作用:
#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);
}
答案 0 :(得分:4)
第二种方法只有在推导T
的另一种方法时才有效。您的用例没有其他功能参数可用于该扣除。
由于函数指针/引用(process_s
)不是std::function
,因此推理在原始尝试中失败。隐式转换不会计算,它必须是一个对象,其类型为std::function
实例,以便推断成功。
假设没有选项可以向函数添加更多参数,您可以选择两个选项:
apply<S>(...)
。std::function
对象,并将其作为第二个函数参数传递给第一次尝试。第二种选择在C ++ 17中可能不那么难看,因为现在有deduction guides可用。因此,调用实际上可以变为apply("abc", std::function{process_s});
答案 1 :(得分:2)
正如@StoryTeller所述,隐式转换不计算在内。
可以考虑的另一个选择是放弃使用std::function
。
然后它会把你带到正确的地方开始编译:
template <typename T>
int apply(string x, int(&fn)(T))
{
T t = { x };
return fn(t);
}
更不用说您也可以避免std::function
的开销。