I am trying to create a simple way to return a pointer to a template function with a special initialization. The best way I can describe this is with actual code.
The reason I am using something like this is because in my actual production code, I have a measure_func
function that calls a function and measures the time it takes to execute that function. The function I am tryng to measure has very long template parameters and trying to get this might make getting the function pointer easier.
#include <functional>
#include <cassert>
template <typename T>
T add (T a, T b) {
return a + b;
}
template <typename T>
T sub (T a, T b) {
return a - b;
}
template <typename F, typename ...A>
std::invoke_result_t<F> do_operation(F func, A &&...args) {
return func( std::forward<A>(args)... );
}
/// Attempt? Doesn't work though
template<template <typename> typename T>
auto get_float_func(T t) {
return &t<float>;
}
int main() {
// here I can create a function or a templated struct that returns the address of add<float>
auto float_add = get_float_func(add);
// here get_float_func returns the address of sub<float>
auto float_sub = get_float_func(sub);
// that way I can more easily call do_operation like this
float ans1 = do_operation(float_add, 1.5, 1.0);
assert(ans1 == 2.5);
float ans2 = do_operation(float_sub, 1.5, 1.0);
assert(ans2 == 0.5);
}
So in the code, get_float_func
returns the address of t<float>
. In the first case t
is the add
template function. Once we have the pointer, we can invoke the result using do_operation
EDIT1:
The reason behind this is because for our class assignment we have to write a parallel merge sort code in 3 different ways. A serial way that uses one thread, a parallel way that splits the work statically, and a threadpool merge sort that dynamically splits the work and assigns it to different threads. Each of these merge sorts are in 3 different namespaces but share the same function declaration. I have a function that you can pass in a function pointer and it will measure the time that function takes and returns it. I want to be able to write something like this:
namespace serial {
template <typename I, typename O = std::less<typename I::value_type>>
void merge_sort(I begin, I end, O op = { })
{ /* code */ }
}
namespace parallel {
template <typename I, typename O = std::less<typename I::value_type>>
void merge_sort(I begin, I end, O op = { })
{ /* code */ }
}
namespace threadpool {
template <typename I, typename O = std::less<typename I::value_type>>
void merge_sort(I begin, I end, O op = { })
{ /* code */ }
}
int main() {
std::vector<int> data = create_random_array();
/// I want to create something that will always return the instantiation of merge_sort<std::vector<int>::iterator, std::less<int>>
/// function pointer
float elapse1 = measure_func(serial::merge_sort, data.begin(), data.end(), std::less<int>{ });
float elapse2 = measure_func(parallel::merge_sort, data.begin(), data.end(), std::less<int>{ });
float elapse3 = measure_func(threadpool::merge_sort, data.begin(), data.end(), std::less<int>{ });
}
The above code does not work because serial::merge_sort and the like are not function pointers, but need template initialization.