简体   繁体   English

当模板用作参数时,传递指向模板函数的指针

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM