我有一个声明如下的函数;它的确切工作与此无关。
template<typename T>
std::pair<int, int>
partition3(T *pT, const int N, const T &Kq, const int w,
std::function<int(const T&, const T&, int)> P);
在通话网站上,我尝试执行以下操作:
bool partition3_test()
{
struct cmp
{
int operator()(int x, int y, int) const
{ return x-y; }
};
int V1[11] = { 3, 7, 1, 7, 7, 8, 10, 2, 16, 4, 3 },
V2[11] = { 3, 6, 1, 6, 6, 8, 10, 2, 16, 4, 3 };
std::function<int(const int&, const int&, int)> F = cmp();
std::pair<int, int>
p1 = partition3(V1, 11, 7, 0, cmp()),
p2 = partition3(V2, 11, 7, 0, cmp());
return false;
}
对于partition3
的两次调用,编译器(MSVC 2010)抱怨它无法推断出最后一个参数的模板参数。如果我将cmp()
替换为F
,则代码会编译并正常运行。
我有两个问题:
F
?(目前,我已通过在partition3
上引入另一个模板参数并将P
声明为该模板类型来解决此问题。)
答案 0 :(得分:4)
cmp()
实际上根本不是std::function
。复制初始化工作的事实可能会混淆问题,但是使用转换构造函数必须使用某种包装器对象,我很惊讶它对一个临时的仿函数对象起作用(啊,检查标准吧显然是制作仿真器的副本)。
除此之外,函数参数不匹配(按值传递和传递const引用是源兼容的,但不兼容运行时调用),这又需要一个适配器。 / p>
最好的解决方案是使模板函数更通用,这样它也适用于原始函数指针和任意函子对象,而不仅仅是std::function
:
template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
const Functor& P);
如果由于某种原因你真的想使用std::function
(例如你需要虚拟调度),你可以。与Nawaz写的相反,这个错误是是一个可推导的上下文,但不止一种类型适合(这是std::function
的适配器/包装器性质变得重要的地方,因为类型不必与参数完全匹配,它只需要兼容。std::function<int(const long&, const long&, int)>
也匹配。)
使用不可推导的上下文,这样编译器甚至不会尝试使用仿函数来推导T
。
template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
std::function<std::identity<const T>::type&, std::identity<const T>::type&, int> P);