[英]Passing pointer to template-function, when the template used as argument
While trying to play around with function pointers, I wondered if there's a way to pass as an argument a template-function pointer, which uses an instance of the template as one of its arguments. 在尝试使用函数指针时,我想知道是否存在一种将模板函数指针作为参数传递的方法,该函数使用模板的实例作为其参数之一。 For example, I have the following template function:
例如,我具有以下模板功能:
template<class T>
bool match(int i, const T& M){
return i%M.val==0;
}
which will eventually take the following class as T: 最终将采用以下类别作为T:
class Num{
public:
int val;
Num(int n): val(n) {}
};
(It's just a training code, I'm not using it for something of course) (这只是一个培训代码,我当然不会使用它)
Now, I have the following function, which is basically an implementation of count_if: 现在,我具有以下功能,该功能基本上是count_if的实现:
int countMod(const vector<int>& v, int mod, **???**){
Num nMod(mod);
int cnt=0;
for(vector<int>::const_iterator it=v.begin(); it!=v.end();it++){
if(match(*it, nMod)){
cnt++;
}
}
return cnt;
}
The method is supposed to return the number of elements divisible by mod
. 该方法应返回可被
mod
整除的元素数。 The third argument is the one I'm not sure about of course. 第三个论点是我不确定的那个。
I want to somehow pass a pointer to the template function match<Num>
, with Num(mod)
as M
. 我想以某种方式将指针传递给模板函数
match<Num>
,其中Num(mod)
为M
I understand that it's quite weird to pass a pointer to something that doesn't actually exist, since I haven't instantiated an actual function, say match, but since the function match
is supposed to get const T&
, I'm really not sure how to sort it out, if possible. 我知道将指针传递到实际上不存在的东西是很奇怪的,因为我还没有实例化一个实际的函数,例如match,但是由于该函数
match
应该得到const T&
,所以我真的不确定如果可能的话,如何解决它。
Edit: I repaired the call to match as mentioned in the first comment, and yet I'm not sure what to pass as argument to countMod
. 编辑:我修复了第一个注释中提到的匹配匹配的调用,但是我不确定将什么作为参数传递给
countMod
。 I guess its something like bool(*match)(int, **???**)
, but I don't know for certain. 我猜它有点像
bool(*match)(int, **???**)
,但是我不确定。
The simpler would be templatize your method 更简单的方法是将您的方法模板化
template <typename F>
int countMod(const vector<int>& v, int mod, F f)
{
Num nMod(mod);
int cnt = 0;
for(vector<int>::const_iterator it=v.begin(); it!=v.end();it++){
if(f(*it, nMod)){
cnt++;
}
}
return cnt;
}
A more descriptive way would be 一种更具描述性的方式是
int countMod(const vector<int>& v, int mod, std::function<bool (int, Num)> f)
{
Num nMod(mod);
int cnt = 0;
for(vector<int>::const_iterator it=v.begin(); it!=v.end();it++){
if(f(*it, nMod)){
cnt++;
}
}
return cnt;
}
and call it in both case 并在两种情况下都调用它
countMod(v, mod, &match<Num>);
As you noted in the comment to Jarod42's answer, there's no real reason to pass in mod
, because the only thing you do with mod
is to feed it back to the function that's also getting passed in. So a logical thing to do is just to restructure your code: 正如您在Jarod42答案的评论中所指出的那样,没有真正的理由要传入
mod
,因为您对mod
所做的唯一一件事就是将其反馈给也要传入的函数。因此,合理的做法是重组代码:
template <typename F>
int count(const vector<int>& v, F f)
{
int cnt = 0;
for(vector<int>::const_iterator it=v.begin(); it!=v.end();it++){
if(f(*it)){
cnt++;
}
}
return cnt;
}
Now, you can just do the following: 现在,您可以执行以下操作:
int mod = 3; // or whatever
auto c = count(v, [nmod = Num(mod)] (int x) { return match(x, nmod); });
Note that this requires C++14, but you can easily modify it to work with 11. What we're doing now, is instead of passing the function directly, we use a lambda to bind one of the arguments before passing it in. This sort of thing is common when working with higher order functions. 请注意,这需要C ++ 14,但是您可以轻松地对其进行修改以使其与11一起使用。我们现在要做的是,不是直接传递函数,而是使用lambda绑定其中一个参数,然后传递给它。使用高阶函数时,这种情况很常见。
Of course, you might notice at this point that count
is looking really generic. 当然,您可能会注意到此时
count
看起来非常通用。 It's really only non-generic in the container argument, insofar as it requires specifically a vector of integers . 就容器参数而言,它实际上只是非泛型的,因为它特别需要整数 向量 。 If we make that part generic too, we end up with a function in the standard library:
count_if
. 如果我们也使该部分通用,那么我们将在标准库中得到一个函数:
count_if
。 Your problem can also be solved as: 您的问题也可以通过以下方式解决:
auto c = std::count_if(v.begin(), v.end(),
[nmod = Num(mod)] (int x) { return match(x, nmod); });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.