Passing a complex function variants as arguments

帅比萌擦擦* 提交于 2019-12-05 21:59:55

The problem is that std::abs (from <complex>) takes the std::complex<T> parameter as a reference-to-const. Your function pointer only says by value, which causes the mismatch. The following code compiles just fine:

#include <vector>
#include <complex>

template <class T>
void apply(const std::vector<std::complex<T> >& in, std::vector<T>& out,
           T (*f)(std::complex<T> const&))
{
    out.resize(in.size());
    for(size_t i = 0; i < in.size(); ++i)
      out[i] = f(in[i]);
}

int main(){
  std::vector<std::complex<float> > vcomp;
  std::vector<float> vf;
  apply(vcomp, vf, &std::abs<float>);
}

Live example on Ideone.

A better idea, however, would be to simply take the function type as a template parameter:

template <class T, class F>
void apply(const std::vector<std::complex<T> >& in, std::vector<T>& out, F f)
{
    out.resize(in.size());
    for(size_t i = 0; i < in.size(); ++i)
      out[i] = f(in[i]);
}

Live example on Ideone.

In any case, you sometimes might need to disambiguate at the call site with a cast, if a function is templated and overloaded (I don't remember one off-hand from the <complex> functions, but you never know).

// taking std::abs as an example. It's not actually templated *and* overloaded
typedef float (*func_ptr)(std::complex<float> const&);
apply(vcomp, vf, (func_ptr)&std::abs<float>);

As far as I can tell, you do not even need to invent apply, as what you want can be done with std::transform:

#include <vector>
#include <complex>
#include <algorithm>

int main(){
  std::vector<std::complex<double> > complex_vec(10);
  std::vector<double> double_vec;
  double_vec.resize(complex_vec.size());
  std::transform(complex_vec.begin(), complex_vec.end(),
                 double_vec.begin(), std::abs<double>);
  return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!