I have the following typedef:
template<typename G, typename T, typename R>
using my_func_type = typename R(T::*)(G, int) const;
It is a member function I use a lot, so I'm playing around with making different wrappers for. The premise is that I want an object that implements these functions through a common function call, so that I can combine them in different ways (currently I use the straightforward way of wrapping the call as a lambdas).
However, another method is to pass that function as a non-type template parameter (this improves my performance compared to the lambda solution, because I'm constantly evaluating it), viz.
template<typename G, typename T, typename R, my_func_type<G, T, R> f>
struct MyWrapper
{
MyWrapper(G g, T t) : g{ g }, t{ t } {}
auto eval(int n) const
{
return (t.*f)(g, n);
}
protected:
G g;
T t;
};
int main()
{
AnObject g;
TheCallingObject t;
auto f = &TheCallingObject::callit;
MyWrapper<AnObject, TheCallingObject, double, f> wrap(g, t)
}
But this seems a little redundant, so is it possible for the template arguments to be deduced from f
?
The halfway solution I've found is:
template<auto f, typename G, typename T>
struct MyWrapper
{
OpFuncDerivative(G g, T t) : g{ g }, t{ t } {}
auto eval(int n) const
{
return (t.*f)(g, n);
}
protected:
G g;
T t;
};
int main()
{
AnObject g;
TheCallingObject t;
auto f = &TheCallingObject::callit;
// it won't automatically deduce AnObject and TheCallingObject
// through the parameters to the constructor though!
MyWrapper<f, AnObject, TheCallingObject> wrap(g, t)
}
You can write a helper function:
template<typename G, typename T, auto f>
struct MyWrapper
{
MyWrapper(G g, T t) : g{g}, t{t}
{}
auto eval(int n) const
{
return (t.*f)(g, n);
}
protected:
G g;
T t;
};
template<auto f, typename G, typename T>
MyWrapper<G, T, f> make_wrapper(G g, T t)
{
return {g, t};
}
and then use it like this:
int main()
{
AnObject g;
TheCallingObject t;
constexpr auto f = &TheCallingObject::callit;
auto wrap = make_wrapper<f>(g, t);
}