Passing complex functional options as arguments

Let's 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 the function to a complex data vector and store the results in a real data vector. I believe this should be good for a whole list of functions: abs, norm, real, imag, etc.

My problem is how to pass the function to?

I tried apply(in, out, abs) options, supplying different abs templates with no luck. I’m sure that the problem is related to functions for all complex templates, but I’m not sure how to transfer it correctly. Thanks for the help.

+3
source share
2 answers

The problem is that std::abs (from <complex> ) takes the std::complex<T> parameter as a reference to a constant. The function pointer speaks only by value, which causes a 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 type of the function 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 may sometimes need to eliminate the ambiguity on the call site with a throw if the function is templated and overloaded (I don’t remember one of the third-party <complex> functions, but you never know).

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

As far as I can tell, you don’t even have to invent apply , because 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; } 
0
source

All Articles