将复杂函数变体作为参数传递

发布于 2025-01-01 23:55:53 字数 502 浏览 4 评论 0原文

假设我有以下模板函数:

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

您可以看到,我只想将函数应用于复杂数据的向量,并将结果存储到真实数据的向量中。我认为这应该适合整个函数列表:abs、norm、real、imag 等。

我的问题是,如何传入函数?

我尝试过 apply(in, out, abs) 的变体为 abs 提供不同的模板,但没有成功。我很确定问题源于复杂的所有模板的功能,但我不确定如何正确传递它。感谢您的帮助。

Say I have the following template function:

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

You can see, I just want to apply a function to a vector of complex data, and store the results into a vector of real data. I figure this should be good for a whole list of function: abs, norm, real, imag, etc.

My problem is, how do I pass a function in?

I have tried variants of apply(in, out, abs) supplying different templates to abs with no luck. I am pretty sure the problem stems from the functions for complex all being templates, but I am not sure how to pass it properly. Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只想待在家 2025-01-08 23:55:53

问题是 std::abs (来自 )将 std::complex 参数作为参考 -至常量。您的函数指针仅按值表示,这会导致不匹配。以下代码编译得很好:

#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>);
}

Ideone 上的实时示例。

然而,更好的想法是简单地采用该函数作为模板参数输入:

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]);
}

Ideone 上的实时示例。

在任何情况下,有时您可能需要在调用站点消除歧义与一个如果函数是模板化的并且重载的(我不记得 函数中的任何一个,但你永远不知道)。

// 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>);

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>);
原谅我要高飞 2025-01-08 23:55:53

据我所知,您甚至不需要发明 apply,因为您想要的可以通过 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;
}

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文