【问题标题】:Passing a complex function variants as arguments将复杂的函数变体作为参数传递
【发布时间】:2012-02-02 13:08:46
【问题描述】:

假设我有以下模板函数:

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 提供不同的模板,但没有成功。我很确定问题源于复杂的所有模板的功能,但我不确定如何正确传递它。感谢您的帮助。

【问题讨论】:

    标签: c++ templates functor


    【解决方案1】:

    问题在于std::abs(来自&lt;complex&gt;)将std::complex&lt;T&gt; 参数作为对const 的引用。您的函数指针仅按值表示,这会导致不匹配。以下代码编译得很好:

    #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.

    然而,一个更好的主意是简单地将函数类型作为模板参数:

    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.

    在任何情况下,如果函数被模板化并且重载(我不记得&lt;complex&gt;中的一个副手),您有时可能需要在调用站点使用强制转换来消除歧义。函数,但你永远不知道)。

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

    【讨论】:

    • pow 是模板化的重载,但它总是需要两个参数。
    • 我不知道abs 和其他复杂的函数需要const&amp;。这似乎并没有一致地记录下来。现在一切正常,谢谢。
    【解决方案2】:

    据我所知,您甚至不需要发明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;
    }
    

    【讨论】:

    • 我意识到,但我的实际功能还有很多,提供的只是说明问题的一个小例子。
    • @steveo225:您的意思是您的apply 功能做得更多,还是您计划与apply 一起使用的功能做得更多?如果是第二个,你很可能仍然可以使用transform
    • 我的apply 函数比显示的要多,只需要一个简单的例子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 2018-08-30
    • 1970-01-01
    • 2014-08-28
    • 2013-08-13
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多