I've been trying to come up with a templated function that generalizes the bounce procedure when dealing with C APIs that use function pointer callbacks.
I've mostly figured it out and have a working system, but I'm wondering if there is a way to clean up the final step.
Imagine you have an API that takes a function pointer and a user data pointer. You want to use an instance method as the callback target. This requires a "bounce" function that reinterprets the user data pointer as an instance pointer and calls the method with the rest of the arguments.
The following example code works:
#include <cstdio>
class Foo {
public:
Foo(int val) : val_(val) { }
void baz(int v) const
{
printf("baz %d\n", v + val_);
}
private:
int val_;
};
// Templated bounce function
template<class T, class Method, Method m, class Ret, class ...Args>
static Ret bounce(void *priv, Args... args)
{
return ((*reinterpret_cast<T *>(priv)).*m)(args...);
}
#define BOUNCE(c, m) bounce<c, decltype(&c::m), &c::m>
// Callback simulator
void call_callback(void (*func)(void *, int), void *priv, int v)
{
if (func) {
func(priv, v);
}
}
// Main Entry
int main()
{
Foo bar(13);
call_callback(&bounce<Foo, decltype(&Foo::baz), &Foo::baz>, &bar, 10);
call_callback(&BOUNCE(Foo, baz), &bar, 11);
return 0;
}
Basically I'm looking for a way to clean up the usage. The macro works but I'm trying to instead find some type of helper function that can just take a method pointer parameter like &Foo::baz and deduce all the parameters. Something like a bounce_gen(&Foo::baz) that would return a pointer to the actual bounce function.
It has been a fun exercise, but I can't quite get the last piece.
The type of a member function pointer contains the class type and the function signature. So, you can let template function argument deduction handle this for you:
template<class T, class Method, class ...Args>
static auto bounce(Method T::*func, T* priv, Args... args) -> decltype((priv->*m)(args...))
{
return (priv->*m)(args...);
}
More convenient might be to either use std::bind or a lambda to completely hide the fact that it is a member function call:
template<class Func, class ...Args>
static auto bounceCallable(Func func, Args... args) -> decltype(func(args...))
{
return func(args...);
}
And you would call it like this:
call_callback([&bar](int v){bar.baz(v);}, 11);
With a lambda, you have a syntax nicer than with std::bind, but it comes at the cost of having to repeat the signature.
Related
I'm writing a simple "wrapper library" around another library and I'm having issues with std::function not being able to deduce template arguments for variadic template functions. To make things more concrete:
There's a library (it's a HTTP server) that I'm planning to "expand" with more functionality and to make it more convenient to use by "other code users" (automatic serialization of data, writing controller functions based on needs etc.). Basically cutting down on a lot of boilerplate code. From now on I'm calling this one simply "library". It cannot be touched or changed.
There's the code that "expands" the functionality above that I write myself and it's where I have the problem. From now on I call this a "wrapper library".
There's the "user code", that is - any code that uses the "wrapper library". I've included examples what I'd like it to look like and I'd rather keep it as simple as possible, especially when it comes to unnecessary template parameters bloat (not having to explicitly pass template arguments when it can be deduced by the compiler etc.). See main in the code below for examples.
Here's the complete example (that doesn't compile):
#include <type_traits>
#include <variant>
#include <vector>
/*** Library code starts here ***/
// Library handler function definition to be registered. This cannot be changed.
// For simplicity I made the function arguments (int, int) to denote that this
// handler function does take some arguments passed later by the library.
// In reality these are simple, non-templated structs.
using LibraryHandler = std::function<void(int, int)>;
std::vector<LibraryHandler> g_libraryHandlers;
void RegisterLibraryHandler(LibraryHandler handler)
{
// Library code registering passed handler. This cannot be changed.
g_libraryHandlers.push_back(handler);
}
/*** End of library code ***/
/*** My "wrapper library" starts here ***/
// ReturnType is the type returned by the functions written by "wrapper library users".
// Types... is the list of all possible types held by 'ReturnType' that a given function is allowed to return.
template<typename T, typename... Types>
static inline constexpr bool isConstructible = (std::is_constructible_v<T, Types> || ...);
template<typename T, typename... Types>
static inline constexpr bool isAssignable = (std::is_assignable_v<T&, Types> || ...);
template<typename... Types>
class ReturnType
{
public:
template<typename T, std::enable_if_t<
isConstructible<T, Types...> &&
isAssignable<T, Types...>,
int> = 0>
static ReturnType Build(const T& data)
{
return ReturnType(data);
}
private:
template<typename T>
ReturnType(const T& data) : m_data(data) { }
std::variant<Types...> m_data;
};
template<typename T>
class ParamType
{
public:
ParamType() { }
const T& GetData() const { return m_data; }
private:
T m_data;
};
/*** This is where my problem is - how to write these functions to allow for
different logic (based on passed function signature) inside nested lambda? ***/
// Version registering functions taking no arguments
template<typename... Types>
void RegisterFunction(std::function<ReturnType<Types...>()> func)
{
auto wrapperLambda = [func](int a, int b) { // Construct lambda to conform with library interface ('LibraryHandler')
// Logic specific for 'func' with signature: ReturnType<Types...>() - step before call
func();
// Logic specific for 'func' with signature: ReturnType<Types...>() - step after call
};
RegisterLibraryHandler(wrapperLambda); // Register lambda inside library
}
// Version registering functions taking arguments through 'ParamType'
template<typename... Types, typename TParam>
void RegisterFunction(std::function<ReturnType<Types...>(const ParamType<TParam>)> func)
{
auto wrapperLambda = [func](int a, int b) { // Construct lambda to conform with library interface ('LibraryHandler')
// Logic specific for 'func' with signature: ReturnType<Types...>(const ParamType<TParam>) - step before call
func();
// Logic specific for 'func' with signature: ReturnType<Types...>(const ParamType<TParam>) - step after call
};
RegisterLibraryHandler(wrapperLambda); // Register lambda inside library
}
// Version registering functions taking library arguments directly
template<typename... Types, typename TParam>
void RegisterFunction(std::function<ReturnType<Types...>(int, int)> func)
{
auto wrapperLambda = [func](int a, int b) { // Construct lambda to conform with library interface ('LibraryHandler')
// Logic specific for 'func' with signature: ReturnType<Types...>(int, int) - step before call
func(a, b);
// Logic specific for 'func' with signature: ReturnType<Types...>(int, int) - step after call
};
RegisterLibraryHandler(wrapperLambda); // Register lambda inside library
}
/*** End of my "wrapper library" ***/
/*** This is how I'd like the "users of the wrapper library" to write the code ***/
struct SomeReturnData { char a; char b; };
struct OtherReturnData { char c; char d; };
struct SomeParameterType { int p; };
// Example 1 - function only ever returning a single type, taking no arguments
ReturnType<SomeReturnData> UserFunctionNoArgs()
{
SomeReturnData data{ 'x', 'y' };
return ReturnType<SomeReturnData>::Build(data);
}
// Example 2 - function taking parameter 'SomeParameterType' and returning 'SomeReturnData' or 'OtherReturnData'
// based on contents of passed argument.
ReturnType<SomeReturnData, OtherReturnData> UserFunctionArgs(const ParamType<SomeParameterType> param)
{
if (param.GetData().p == 1000)
return ReturnType<SomeReturnData, OtherReturnData>::Build(SomeReturnData());
return ReturnType<SomeReturnData, OtherReturnData>::Build(OtherReturnData());
}
// Example 3 - function requesting library arguments to be passed directly
ReturnType<SomeReturnData, OtherReturnData> UserHandlingLibraryDirectly(int libraryArg1, int libraryArg2)
{
if (libraryArg1 == libraryArg2)
return ReturnType<SomeReturnData, OtherReturnData>::Build(SomeReturnData());
return ReturnType<SomeReturnData, OtherReturnData>::Build(OtherReturnData());
}
int main()
{
// User registers written functions in the "wrapper library".
// This includes any 'regluar functions'...
RegisterFunction(UserFunctionNoArgs);
RegisterFunction(UserFunctionArgs);
RegisterFunction(UserHandlingLibraryDirectly);
// ... or lambdas with captures (all possible parameter combinations from examples above apply).
int someInt = 123;
auto userLambda = [someInt]() -> ReturnType<SomeReturnData, OtherReturnData> {
if(someInt < 100)
return ReturnType<SomeReturnData, OtherReturnData>::Build(SomeReturnData());
return ReturnType<SomeReturnData, OtherReturnData>::Build(OtherReturnData());
};
return 0;
}
My issue is with the RegisterFunction above - I'd basically want to write it the way it is above, which is obviously not possible (the compiler complains about not being able to deduce template parameters). My goal is to not change / cut down on possibilities / make any more complicated anything that's inside main.
Lambdas are not std::function, so cannot be deduced. Fortunately, std::function has CTAD (c++17) allowing to solve your issue with an extra overload:
template<typename Func>
void RegisterFunction(Func func)
{
RegisterFunction(std::function{func}); // forward to overload taking std::function
}
Demo
I've been reading a tutorial by Ben Hoffman (https://benhoffman.tech/cpp/general/2018/11/13/cpp-job-system.html)
I've had a go at bashing together a version of the Job/Worker system he has, but instead of using void* for arguments then casting to a known struct, I've been trying to use variadic arguments. The idea is, a job takes in a "parent" to perform a method on, the function pointer to said method, and an Args... for the argument(s). However, I get an internal compiler error if I try to build. Here is the job class:
template <class T, typename... Args>
struct JobMemberFunc : IJob
{
JobMemberFunc(T* aParent, void (T::* f)(Args...), Args... Args)
{
parentObj = aParent;
func_ptr = f;
saved_args = ::std::make_tuple (::std::move(Args)...);
}
virtual bool invoke() override
{
if (!parentObj) { return false; }
(parentObj->*func_ptr)(::std::move(saved_args));
return true;
}
/** the object to invoke the function pointer on */
T* parentObj;
/** The function pointer to call when we invoke this function */
void (T::* func_ptr)(Args...);
::std::tuple<Args...> saved_args;
};
struct CpuJob
{
IJob* jobPtr = nullptr;
};
Then there's the AddJob method, where the internal compiler error is actually happening.
template <typename T, typename... Args>
void AddJob(T* aParent, void(T::* func_ptr)(Args...), Args... args)
{//This curly bracket is where the internal compiler error happens
CpuJob aJob = {};
JobMemberFunc<T, Args...>* jobPtr = new JobMemberFunc<T, Args...>(aParent, func_ptr,
std::forward<Args>(args)...);
aJob.jobPtr = jobPtr;
locklessReadyQueue.enqueue(aJob);
}
More than happy to be told this is a bad/wrong way of trying to do it anyway. I have thought about doing away with it and having a standardized argument list or doing something polymorphic but I really wanna make this work so I can literally ask the job system to do anything I like.
Thanks!
std::function<void()> (in combination with lambdas) already do what you're trying to do with JobMemberFunc.
void AddJob(std::function<void()>&& job)
{
locklessReadyQueue.enqueue(std::move(job));
}
With this you can submit any function call as a job.
For example, a call some_obj.some_method(some_arg) becomes:
AddJob([&] { some_obj.some_method(some_arg); });
No more ugly pointer-to-member stuff...
You can find more complete thread pooling examples here: Thread pooling in C++11
I'm trying to pass a function pointer as a parameter of another function, but the function pointer may or may not itself have an argument (making it different from the other questions I searched for).
The code works as is, but MY problem is that I was trying to use a single function and pass in each different function pointer, but what I have below is 3 different functions to pass each function pointer. I'd like to get rid of the 3 different function definitions as they are all the same with the exception of the passed in function pointer (so basically, 3 copies of execute_func() definitions). Here's what I have so far but this doesn't seem right that I should need three execute_func() calls.
class A { ... };
class B { ... };
class Test {
private:
std::function<void()> fp;
std::function<void(MyA &)> fp;
std::function<void(MyB &)> fp;
// ...
};
// Here I create a function pointer for each of my calls.
Test::Test() {
fp = std::bind(&Test::do_this, this);
fp_a = std::bind(&Test::do_a, this, std::placeholders::_1);
fp_b = std::bind(&Test::do_b, this, std::placeholders::_1);
}
// Here my intention was to have only 1 execute_func() call and I would
// pass in the pointer to the function that I want to call.
Test::test_it()
{
A a;
B b;
execute_func(fp);
execute_func(fp_a, a);
execute_func(fp_b, b);
}
// I was hoping to only need one function, but so far
// have needed 3 functions with diff signatures to make it work.
bool Test::execute_func(std::function<void()> fp) {
// ... more code here before the fp call
fp();
// ... them more common code here.
}
bool Test::execute_func(std::function<void(MyA &)> fp, MyA &a) {
// ... more common code here
fp(a);
// ... and more common code here
}
bool Test::execute_func(std::function<void(MyB &)> fp, MyB &b) {
// ... more common code here
fp(b);
// ... and more common code here.
}
// And of course the execute_func() calls call these members as passed in.
bool Test::do_this() { ... }
bool Test::do_a(MyA &a) { ... }
bool Test::do_b(MyB &b) { ... }
Thoughts on where I'm going wrong?
To do this you can use a variadic template.
template<typename Ret, typename... Args>
bool Test::execute_func(Ret fp(Args&&...), Args&&... args)
{
// do stuff
fp(args...);
// do more stuff
}
I'm using an ordinary function pointer here instead of std::function, which is, IMO, baroque and wholly unnecessary (it's a relic from when C++ didn't have lambdas). But it's the same idea.
template<typename Ret, typename... Args>
bool Test::execute_func(const std::function<Ret(Args&&...)> &fp, Args&&... args) { }
Edit: Jarod42 points out that you can make it so it will work with both function pointers, std::function and any other callable object as follows:
template<typename Func, typename... Args>
bool Test::execute_func(Func &&fp, Args&&... args)
{
// do stuff
fp(args...);
// do more stuff
}
To make it even more generic you can use std::invoke to call fp instead of directly calling it, which additionally allows fp to be a member function or data member (with the instance pointer given in the first subsequent argument).
template<typename Func, typename... Args>
bool Test::execute_func(Func &&fp, Args&&... args)
{
// do stuff
std::invoke(fp, args...);
// do more stuff
}
The previous example could also equivalently be written
template<typename... InvokeArgs>
bool Test::execute_func(InvokeArgs&&... iargs)
{
// do stuff
std::invoke(iargs...);
// do more stuff
}
Say I'm using a C API that lets you register callbacks that take a void* closure:
void register_callback(void (*func)(void*), void *closure);
In C++ it's nice to have stronger types than void* so I want to create a wrapper that lets me register strongly-typed C++ callbacks instead:
template <typename T, void F(T*)>
void CallbackWrapper(void *p) {
return F(static_cast<T*>(p));
}
void MyCallback(int* param) {}
void f(void *closure) {
register_callback(CallbackWrapper<int, MyCallback>, closure);
}
This works alright. One nice property of this solution is that it can inline my callback into the wrapper, so this wrapping scheme has zero overhead. I consider this a requirement.
But it would be nice if I could make the API look more like this:
void f2() {
RegisterCallback(MyCallback, closure);
}
I hope I can achieve the above by inferring template parameters. But I can't quite figure out how to make it work. My attempt so far is:
template <typename T>
void RegisterCallback(void (*f)(T*), T* closure) {
register_callback(CallbackWrapper<T, f>, closure);
}
But this doesn't work. Anyone have a magic incantation that will make f2() work above, while retaining the zero-overhead performance characteristic? I want something that will work in C++98.
This template function improves the syntax marginally.
template <typename T, void F(T*)>
void RegisterCallback (T *x) {
register_callback(CallbackWrapper<T, F>, x);
}
int x = 4;
RegisterCallback<int, MyCallback>(&x);
If you are willing to use a functor rather than a function to define your callback, then you can simplify things a bit more:
#ifdef HAS_EXCEPTIONS
# define BEGIN_TRY try {
# define END_TRY } catch (...) {}
#else
# define BEGIN_TRY
# define END_TRY
#endif
template <typename CB>
void CallbackWrapper(void *p) {
BEGIN_TRY
return (*static_cast<CB*>(p))();
END_TRY
}
struct MyCallback {
MyCallback () {}
void operator () () {}
};
template <typename CB>
void RegisterCallback (CB &x) {
register_callback(CallbackWrapper<CB>, &x);
}
MyCallback cb;
RegisterCallback(cb);
But, as others have mentioned, you run the risk of the code not porting correctly to a system where the C ABI and C++ ABI differ.
I have discovered a better answer to this question than the other answers given to me here! (Actually it was another engineer inside Google who suggested it).
You have to repeat the function name twice, but that can be solved with a macro.
The basic pattern is:
// Func1, Func2, Func3: Template classes representing a function and its
// signature.
//
// Since the function is a template parameter, calling the function can be
// inlined at compile-time and does not require a function pointer at runtime.
// These functions are not bound to a handler data so have no data or cleanup
// handler.
template <class R, class P1, R F(P1)>
struct Func1 {
typedef R Return;
static R Call(P1 p1) { return F(p1); }
};
// ...
// FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
// *signature*, but without a specific function attached.
//
// These classes contain member functions that can be invoked with a
// specific function to return a Func/BoundFunc class.
template <class R, class P1>
struct FuncSig1 {
template <R F(P1)>
Func1<R, P1, F> GetFunc() { return Func1<R, P1, F>(); }
};
// ...
// Overloaded template function that can construct the appropriate FuncSig*
// class given a function pointer by deducing the template parameters.
template <class R, class P1>
inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
(void)f; // Only used for template parameter deduction.
return FuncSig1<R, P1>();
}
// ...
// Function that casts the first parameter to the given type.
template <class R, class P1, R F(P1)>
R CastArgument(void *c) {
return F(static_cast<P1>(c));
}
template <class F>
struct WrappedFunc;
template <class R, class P1, R F(P1)>
struct WrappedFunc<Func1<R, P1, F> > {
typedef Func1<R, void*, CastArgument<R, P1, F> > Func;
};
template <class T>
generic_func_t *GetWrappedFuncPtr(T func) {
typedef typename WrappedFunc<T>::Func Func;
return Func().Call;
}
// User code:
#include <iostream>
typedef void (generic_func_t)(void*);
void StronglyTypedFunc(int *x) {
std::cout << "value: " << *x << "\n";
}
int main() {
generic_func_t *f = GetWrappedFuncPtr(
MatchFunc(StronglyTypedFunc).GetFunc<StronglyTypedFunc>());
int x = 5;
f(&x);
}
This is not short or simple, but it is correct, principled, and standard-compliant!
It gets me what I want:
The user gets to write StronglyTypedFunc() taking a pointer to a specific thing.
This function can be called with a void* argument.
There is no virtual function overhead or indirection.
Why not make your closure a real closure (by including real typed state).
class CB
{
public:
virtual ~CB() {}
virtual void action() = 0;
};
extern "C" void CInterface(void* data)
{
try
{
reinterpret_cast<CB*>(data)->action();
}
catch(...){}
// No gurantees about throwing exceptions across a C ABI.
// So you need to catch all exceptions and drop them
// Or probably log them
}
void RegisterAction(CB& action)
{
register_callback(CInterface, &action);
}
By using an object you can introduce real state.
You have a clean C++ interface with correctly types objects.
Its easy to use you just derive from CB and implement action().
This also has the same number of actual function calls as you use. Because in your example you pass a function pointer to the wrapper (which can't be inlined (it can but it will take more static analysis then current compilers do)).
Apparently it does inline.
I am currently in the process of writing a method execution queue in C++x0. I have implemented and verified the basic queue mechanism but want to amend it with an option to have push() automatically remove all previous calls to a specific method:
queue.push(this, &Obj::foo, 1);
queue.push(this, &Obj::foo, 2);
queue.push(this, &Obj::foo, 3);
should be the same as merely calling
queue.push(this, &Obj::foo, 3);
My code thus far looks like this:
Queue.h:
#pragma once
#include <functional>
#include <vector>
using std::vector;
using std::function;
using std::bind;
class Queue
{
private:
struct functioncall {
std::function<void()> call;
};
vector<functioncall> queue;
public:
Queue();
~Queue();
template<typename T, typename F, typename... Args>
int push(T, F , Args... args);
int pop();
bool empty();
size_t size();
};
template<typename T, typename F, typename... Args>
int Queue::push(T instance, F func, Args... args)
{
functioncall newelem = { bind(func, instance, args...) };
queue.push_back(newelem);
return queue.size();
}
Queue.cpp:
#include "Queue.h"
Queue::Queue() : queue()
{
}
Queue::~Queue()
{
delete &queue;
}
int Queue::pop()
{
if(!queue.empty())
{
queue.front().call();
queue.erase(queue.begin());
return queue.size();
}
return 0;
}
bool Queue::empty()
{
return queue.empty();
}
size_t Queue::size()
{
return queue.size();
}
I have already prepared the vector queue to take a struct in wich I want to not only save the result of std::bind but also the pointer to the method being called so I can look for that pointer and remove the old entries.
The issue is that the functions passed to push() can take an arbitrary amount of arguments. Is there a generic pointer type (it doesn't have to be executable, just be the same when I repeatedly push the same function to the queue) that can do that?
Per 5.2.10p10, you can cast a pointer to member function T::*(A1, A2, ...) to another pointer to member function type U::*(B1, ...) and back with no loss of information; std::less can compare pointers to member functions so by casting to a dummy pointer-to-member type void (Impl::*)() you can compare pointer to member functions with the same signature.
However, it is not guaranteed that pointer to member functions with different signatures will compare different when cast to the same pointer to member type, so you will need to encode the signature in your comparable type. typeid will work here:
auto key = std::make_pair(&typeid(F), reinterpret_cast<void (Queue::*)()>(func));
This assumes that F is indeed a pointer to member function; if the user attempts to pass some other callable object then this will break.
std::function::target<>() can be used to check wrapped function type:
template <class F> bool is_same_call(const functionalcall& prevCall, F newCall)
{
const F* pf = prevCall.call.target<F>();
return pf ? *pf == newCall : false;
}
Note that std::function::target() will return nullptr if function wrapped with std::function object has type different from F.