C++ Function Call Wrapper with Function as Template Argument

C++ function call wrapper with function as template argument

#include <utility>
#include <iostream>

struct c_api_interface { int (*func_a)(int, int); int (*func_b)(char, char, char); };
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }

template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args... args) {
std::cout << "and ....it's a wrap ";
return fn(std::forward<Args>(args)...);
}
#define WRAPIT(FUNC) wrapper<decltype(&FUNC), &FUNC>

int main() {
c_api_interface my_interface;
my_interface.func_a = WRAPIT(foo);
my_interface.func_b = WRAPIT(bar);

std:: cout << my_interface.func_a(1,1) << std::endl;
std:: cout << my_interface.func_b('a','b', 1) << std::endl;

return 0;
}

see http://rextester.com/ZZD18334

C++ function wrapper of a function with a template argument

typedef FT (*Implicit_function)(FT, FT, FT);

You declared that the function accepts the same type for all 3 parameters, and also returns the very same type.

Should have been typedef FT (*Implicit_function)(FT, FT, Point_vec);

Fix the signature of Implicit_function, and your problem should be gone.

In case this is at least C++11, you should also be preferring std::function over raw function pointer so that functions or lambdas with bindings / captures can be accepted.

FT_to_point_function_wrapper::function should be declared const as it is only set by initializer list in constructor. If using C++11, you may then also declare FT_to_point_function_wrapper::FT_to_point_function_wrapper to be constexpr.

FT_to_point_function_wrapper::operator() should be declared to be const as well.

C++ function call wrapper object with function as template argument

At no point in the program you specify Args and it can’t be deduced so it turns out to be an empty pack.

You can capture the arguments of the function using a partial specialization:

template<auto F> class C;
template<typename RV, typename ...Args, RV (*F)(Args...)>
class C<F>
{
...

C++ function call wrapper with class member function as template argument

The problem with member function is they need an object of the class to be called.

Supposing you can pass the object of the class, together with the pointer to the member function, to the constructor, I suppose you can write the wrapper as follows

template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...)>
{
private:
std::function<Ret(Args...)> m_f;

public:
wrapper (Cl cl, Ret(Cl::*m)(Args...))
: m_f{ [=](Args... as) mutable { return (cl.*m)(as...); } }
{ }

Ret operator() (Args... args) const
{ return m_f(args...); }
};

The following is a full compilable example of use

#include <functional>
#include <iostream>

template <typename F>
class wrapper;

template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...)>
{
private:
std::function<Ret(Args...)> m_f;

public:
wrapper (Cl cl, Ret(Cl::*m)(Args...))
: m_f{ [=](Args... as) mutable { return (cl.*m)(as...); } }
{ }

Ret operator() (Args... args) const
{ return m_f(args...); }
};

struct foo
{
long long bar (int a, long b, long long c)
{ return a+b+c; }
};

int main ()
{
foo f;

wrapper<decltype(&foo::bar)> wfb{f, &foo::bar};

std::cout << wfb(1, 2l, 3ll) << std::endl;
}

Observe that the example works for a not-const member functions.

For const member functions, you could need another wrapper

template <typename Ret, typename Cl, typename ...Args>
class wrapper <Ret(Cl::*)(Args...) const>
{
private:
std::function<Ret(Args...)> m_f;

public:
wrapper (Cl const & cl, Ret(Cl::*m)(Args...) const)
: m_f{ [=](Args... as) { return (cl.*m)(as...); } }
{ }

Ret operator() (Args... args) const
{ return m_f(args...); }
};

In both cases, you could improve a little the operator() adding perfect forwarding

  template <typename ... As>   
Ret operator() (As && ... as) const
{ return m_f(std::forward<As>(as)...); }

Template function wrapper

There is significant difference between:

(&Wrapper<decltype (fun)>::template invoke<T>);

and

(&Wrapper<decltype(&test)>::template invoke<&test>);

in the former you use T which is obviously the type of the function you pass in the latter you provide the pointer to function to the invoke method. As invoke method accepts non-type template parameter, here function pointer, the second code compiles correctly. Remember - you cannot mix non-type template parameters with type template parameters just like you cannot mix type template parameters with template template parameters.

Use member function as template argument to create a static wrapper

The simple answer for C++11 is: You can't!

From C++17 you are able to use auto also for non type template parameters as a function pointer or member function pointer is not a type here and you have no syntax to describe your function pointer type.

In C++17 you can use it like this:

struct foo 
{
void bar(){}
};

template <typename T, T>
struct helper;

template <typename T, typename R, typename... Args, R(T::*Func)(Args...)>
struct helper<R(T::*)(Args...), Func>
{
static void reg_handler(const char* name)
{
// ... here your code continues
}
};

template < auto T >
struct X
{
};

template <typename T, typename R, typename... Args, R(T::*Func)(Args...)>
struct X<Func>
{
static void register_handler( const char* name )
{
helper<R(T::*)(Args...), Func>::reg_handler(name);
}
};

int main()
{
X<&foo::bar>::register_handler("check");
}

How to write a template wrapper method for other class member functions?

Try this,

#include <algorithm>
#include <functional>
#include <iostream>

class A
{
public:
void foo(int x) {
std::cout << "Foo: " << x << std::endl;
}

void bar(int x, float y) {
std::cout << "Bar: " << x << ", " << y << std::endl;
}
};

class B
{
public:
void fooAndMore(int x) {
foobarWrapper(&A::foo, x);
}

void barAndMore(int x, float y) {
foobarWrapper(&A::bar, x, y);
}

template<typename T, typename... Args>
void foobarWrapper(T func, Args&&... args)
{
std::cout << "Start!" << std::endl;

auto caller = std::mem_fn( func); // Newly added lines
caller( A(), args...); // Newly added line

std::cout << "End!" << std::endl;
}
};

int main()
{
B b;
b.fooAndMore(1);
b.barAndMore(2, 3.5f);
}

output:

Start!
Foo: 1
End!
Start!
Bar: 2, 3.5
End!

See this link for more details std::mem_fn

How to declare the template argument for an overloaded function

You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:

use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);

Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:

void do_something(int) {}

void do_something(double) {}

template<typename F> void use_funct(F funct) {
funct(1); // calls do_something(int)
funct(1.0); // calls do_something(double)
}

int main() {
use_funct([](auto x){ do_something (x); });
}

[...] possibly without referring to a function pointer?

I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:

using func_type = void();
use_funct<func_type>(do_something);


Related Topics



Leave a reply



Submit