0

I have a template that has a function pointer as it's 2nd parameter and a type that the function pointer is dependent on as it's first.

i.e.

template <typename P, typename void(*fn)(P)>
auto function(P) -> otherType<P, fn>;

I want to make it so that I can just specify the function pointer in the template list without having to specify the dependent type as that type should somehow be able to be inferred from the function pointer that I specify (or maybe even the parameter list, but I think that it probably is too far down the line).

My first thought was to defer the conversion to a template parameter value, by passing a template typename and then convert to a value after the fact though template metaprogramming wizardry.

i.e.

template <typename F, typename P>
auto function(P) -> [[ something here to get otherType<P, fn> if F was a function pointer ]]

However, I'm not sure how I can do this. Any ideas?

Edit

What I'm trying to accomplish here is to make a helper function that will generate a class object. So, given what was said by StenSoft, this is what I've come up with. Unfortunately it doesn't work with a failure inside the main() function where it cannot match to the correct function due to deduction failure:

#include <iostream>
#include <functional>

template<typename T, typename F>
struct wrapper_fntor
{
  T m_t;
  F m_f;
  wrapper_fntor(T t, F f) : m_t(t), m_f(f) {}
  void invoke() { m_f(m_t); }
};

template<typename T, void(*fn)(T)>
struct wrapper_fn
{
  T m_t;
  wrapper_fn(T t) : m_t(t) {}
  void invoke() { fn(m_t); }
};

template <typename T>
struct Wrapper;

template <typename Ret, typename P>
struct Wrapper<Ret(P)>
{
    template <Ret(*fn)(P)>
    static Ret function(P p)
    {
        return fn(std::forward<P>(p));
    }
    template <Ret(*fn)(P)>
    static P get_param_type(P);

    typedef decltype(get_param_type<Ret(P)>()) param_t;
};

template<typename F>
wrapper_fn<typename Wrapper<F>::param_t, &Wrapper<F>::function> make_wrapper(typename Wrapper<F>::param_t param)
{
  return wrapper_fn<typename Wrapper<F>::param_t, &Wrapper<F>::function>(param);
}

template<typename F>
wrapper_fntor<typename Wrapper<F>::param_t, F> make_wrapper(typename Wrapper<F>::param_t param, F fntor)
{
  return wrapper_fntor<typename Wrapper<F>::param_t, F>(param, fntor);
}


void function(int value)
{
    std::cout << "function called " << value << std::endl;
}

int main()
{
    auto x = make_wrapper<function>(3);
    x.invoke();
}

demo

Adrian
  • 10,246
  • 4
  • 44
  • 110
  • 1
    [c++ template parameter type inference](http://stackoverflow.com/q/27372492/3953764) – Piotr Skotnicki Aug 11 '15 at 07:23
  • @PiotrSkotnicki: Thanks. That is unfortunately the answer I was looking for. I.e. that it can't be done as of yet. :-( – Adrian Aug 11 '15 at 15:33
  • There are few problems: `get_param_t` expects function pointer but you provide it function type in definition of `param_t`. Instead of `decltype(get_param_type())`, simply use `P`. `Wrapper` expects function type but you provide it function pointer. Use `Wrapper`. `Wrapper::function` is a template, you need to specify its parameter: `Wrapper::function`. And most importantly, it's impossible to declare `make_wrapper` in the way you want. That's why I use macro, not template method. – StenSoft Aug 15 '15 at 02:08

1 Answers1

1

For a similar problem I have used a templated function inside a templated wrapper class and a macro (this actually works with any parameters and return type):

template <typename T>
struct Wrapper;

template <typename Ret, typename... Params>
struct Wrapper<Ret(Params...)>
{
    template <Ret(*fn)(Params...)>
    static Ret function(Params... params)
    {
        return fn(std::forward<Params>(params)...);
    }
};

#define FUNCTION(fn) \
    Wrapper<decltype(fn)>::function<fn>
StenSoft
  • 9,369
  • 25
  • 30
  • Hmm, maybe it's just too early in the mornings but I don't get it. Maybe give an example of its usage? – Adrian Aug 11 '15 at 13:15
  • @Adrian To use it, just use the macro: `FUNCTION(theFunctionYouWantToPassToTemplate)`. It will return the appropriate `function` instance with filled template parameters (`Ret`, `Params...` and `fn`) that you can use for `otherType`. In this example, it returns a function that can be used to call `fn` (`FUNCTION(theFunction)(param1, param2, param3)`) so it is not much useful but you can easily change that to return something else. – StenSoft Aug 11 '15 at 13:52
  • Sorry, I'm still not getting it. I've updated my question in hopes that you can understand what I'm trying to accomplish. – Adrian Aug 11 '15 at 14:59