0
votes

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?

NOTE ADDED

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 ifs 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.

1
I'm a bit confused. Is it possible to achieve the same result without using a variable template (I discovered that they were introduced in c++14 and I must attain to C++11)? - MaPo
why you require fp to be a function pointer? why not a lambda? since C++14 you can define fp as [](my_map_t& map, int key, auto&& obj, auto func){ inner(map, key, std::forward<decltype(obj)>(obj), func); }, or define a functor same as this lambda in C++11. - RedFog
My point is thatI would have to define the functor (since I use c++11) inside a function. Is it possible? - MaPo
no. similar to this question and others these days, you want some functors to have a template interface but to be a single type. that's impossible, unless there is virtual function template in future C++. - RedFog
Issue with your "function pointer" is that you cannot really capture extra data (you pass lambda currently). std::function<void(my_map_t&, int)> might be what you want instead of function pointer. - Jarod42

1 Answers

3
votes
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.