I have written the following code, which shall do element-wise transformation on arrays of the type x=a op b. T is numeric type (float, double, int, uint8_t, uint32_t, ...)
template <typename T>
void processFrame(Args ARG, T* a_array, T* b_array, T* x_array, uint32_t elmcount)
{
if(ARG.multiply)
{
std::transform(A_array, A_array + elmcount, B_array, x_array, std::multiplies());
} else if(ARG.divide)
{
std::transform(A_array, A_array + elmcount, B_array, x_array, std::divides());
} else if(ARG.min)
{
std::transform(A_array, A_array + elmcount, B_array, x_array, [](T i, T j) {return std::min(i, j);});
}
}
The problem with this code is that I need to repeat the std::transform line multiple times but only transform type really changes. After googling I ended up with using pointer to function populated by lambda.
template <typename T>
using Operator = T (*)(const T&, const T&);
template <typename T>
void processFrame(Args ARG, T* A_array, T* B_array, T* x_array, uint32_t elmcount)
{
Operator<T> op = nullptr;
if(ARG.multiply)
{
op = [](const T &i, const T &j) { return T(i * j); };
} else if(ARG.divide)
{
op = [](const T &i, const T &j) { return T(i / j); };
} else if(ARG.inverseDivide)
{
op = [](const T &i, const T &j) { return T(j / i); };
} else if(ARG.add)
{
op = [](const T &i, const T &j) { return T(i + j); };
} else if(ARG.subtract)
{
op = [](const T &i, const T &j) { return T(i - j); };
} else if(ARG.max)
{
op = [](const T &i, const T &j) { return std::max(i, j); };
} else if(ARG.min)
{
op = [](const T &i, const T &j) { return std::min(i, j); };
}
std::transform(A_array, A_array + elmcount, B_array, x_array, op);
}
Now it is working but I am not sure if I don't use unallocated memory. As op is formally pointer and I initialize it by lambda , shall not that lambda go out of scope at the end of each if block? Is my std::transfrom not using pointer to non existing object?
The code is safe.
Function pointers are valid throughout the length of the program (with exception of dlopen stuff...).
Lambdas without capture are implicitly convertible to function pointers through magic. Each lambda expression creates a distinct type and returns a new object of that type.
Yes, the object goes out of scope, but the type of course doesn't, neither does its static methods which will be the function stored inside the pointer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With