Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply function to all elements in array (in C++ template class)

I have a template class that stores an array of numbers and I want to apply existing (scalar) functions to every element. For example, if we assume my class is std::vector, then I want to be able to call (for example) the std::cos function on all elements.

Maybe a call would look like this:

std::vector<float> A(3, 0.1f);
std::vector<float> B = vector_function(std::cos, A);

N.B. I must also handle std::complex<> types (for which the appropriate complex std::cos function is called).

I found this answer which suggests taking the function type as a template parameter:

template<typename T, typename F>
std::vector<T> vector_function(F func, std::vector<T> x)

However, I couldn't get this to work at all (maybe because functions like std::sin and std::cos are both templated and overloaded?).

I also tried using std::transform, but this quickly became very ugly. For non-complex types, I managed to get it working using a typedef:

std::vector<float> A(2, -1.23f);
typedef float (*func_ptr)(float);
std::transform(A.begin(), A.end(), A.begin(), (func_ptr) std::abs);

However, attempting the same trick with std::complex<> types caused a run-time crash.

Is there a nice way to get this working? I have been stuck on this for ages.

like image 962
Harry Avatar asked Apr 06 '15 09:04

Harry


People also ask

How do you apply a function to all elements of an array?

To apply a function to every item in an array, use array_map() . This will return a new array. $array = array(1,2,3,4,5); //each array item is iterated over and gets stored in the function parameter. $newArray = array_map(function($item) { return $item + 1; }, $array);

When use template C++?

Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates. C++ template is also known as generic functions or classes which is a very powerful feature in C++.

When we specialize a function template it is called?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

How do I use an array template in C++?

Here is the assignment: Create a class template that contains two private data members: T * array and int size. The class uses a constructor to allocate the array based on the size entered. There is member function that allows the user to fill in the array based on the size.


1 Answers

I still think you should use std::transform:

template <class OutputIter, class UnaryFunction>
void apply_pointwise(OutputIter first, OutputIter last, UnaryFunction f)
{
    std::transform(first, last, first, f);
}

This function works not only for std::vector types but indeed any container that has a begin() and end() member function, and it even works for C-style arrays with the help of the free functions std::begin and std::end. The unary function may be any free function, a functor object, a lambda expression or even member functions of a class.

As for the problem with std::sin, this free function is templated and so the compiler cannot know which template instantiation you need.

If you have access to C++11, then simply use a lambda expression:

std::vector<float> v;
// ...
apply_pointwise(v.begin(), v.end(), [](const float f)
{
    return std::sin(f);
});

This way, the compiler knows that it should substitute T=float as the template parameter.

If you can use C functions, you can also use the function sinf, which is not templated and takes a float as a parameter:

apply_pointwise(v.begin(), v.end(), sinf);
like image 51
rwols Avatar answered Sep 29 '22 09:09

rwols