Reputation: 781
I have the following code
using my_map_t = std::map<int, Object<double>>;
using my_map_iterator_t = my_map_t::iterator;
template <typename FWD, typename Func>
void inner(my_map_t& map, int key, FWD&& obj, Func emplacer) {
emplacer(map, key, std::forward<FWD>(obj));
}
my_map_t map;
template <typename FWD>
void outer(my_map_t& map, int key, FWD&& obj)
{
auto lambda = [](my_map_t& m, int k, FWD&& o) {
m.emplace(k, std::forward<FWD>(o));
};
inner(map, key, std::forward<FWD>(obj), lambda);
}
which compiles painlessly. So this means that he deduce automatically the template argument of inner
function.
However, if I introduce a function pointer I need to specify the function pointer template argument, otherwise the compiler complaints
using my_map_t = std::map<int, Object<double>>;
using my_map_iterator_t = my_map_t::iterator;
template <typename FWD, typename Func>
void inner(my_map_t& map, int key, FWD&& obj, Func emplacer) {
emplacer(map, key, std::forward<FWD>(obj));
}
template <typename FWD, typename Func>
void(*fp)(my_map_t&, int, FWD&&, Func) = &inner;
my_map_t map;
template <typename FWD>
void outer(my_map_t& map, int key, FWD&& obj)
{
auto lambda = [](my_map_t& m, int k, FWD&& o) {
m.emplace(k, std::forward<FWD>(o));
};
(*fp<FWD, decltype(lambda)>)(map, key, std::forward<FWD>(obj), lambda);
}
Why in the case of function pointer the argument deduction is not working any more? Did I make some mistake? Is there a way to achieve a better syntax?
I need to use function pointer because I have some function with the same signature of inner
. Let us call them inner1
, inner2
and inner3
. They are called by some outer function
void outer(...) {
if(...) {
inner1(...)
} else if (...) {
inner2(...)
} else {
inner3(...)
}
some_long_task(...)
}
Now in my case the outer
function is called cyclically. The checks in the if
s can be time consuming and they are independent of the argument of outer
function. I was thinking while the some_long_task
is being executed, to set up a function pointer to the right
function inner1
, inner2
or inner3
exploiting some cpu parallelism, so that, the the new cycle begin, I do not have to waste time doing the if check.
Upvotes: 0
Views: 481
Reputation: 180630
template <typename FWD, typename Func>
void(*fp)(my_map_t&, int, FWD&&, Func) = &inner;
is not a normal function pointer. It is what's called a variable template. When you have a variable template, in order to refer to a specific instantiation, you must specify the template parameters. To demonstratre that, consider
template <typename T>
constexpr T pi = T(3.1415926535897932385L);
You can't just do cout << pi
because we don't know which pi
to use. The same occurs with
(*fp<FWD, decltype(lambda)>)(map, key, std::forward<FWD>(obj), lambda);
Here fp
needs the <FWD, decltype(lambda)>
so the compiler can know which specific fp
instance to refer to. It has to do this even before it evaluates the function call because it needs to check the parameters against the function.
What we would need to not have to specify the parameter is a future like CTAD but would work for function pointer variable temapltes.
Upvotes: 3