obtain function pointer of bound/inferred capturing lambda with static local variable - c++

Is it possible to obtain a C style function pointer of a capturing lambda using static local variables?
I am trying to bind the first the argument of the derived function to the original parameter
template <typename F>
class entry_hook
{
public:
entry_hook(void* original, F&& hook)
{
static auto bound = [&](auto&&... args)
{
return hook(original, std::forward<decltype(args)>(args)...);
};
auto* function_ptr = +[](auto&&... args) // -> decltype(bound(std::forward<decltype(args)>(args)...))
{
return bound(std::forward<decltype(args)>(args)...);
};
}
};
Using:
const auto hook = entry_hook(nullptr, [](void* original)
{
// ...
});
Fails to compile - unable to convert closure to function pointer
Removing the parameter pack from the wrapping lambda (by changing the following lines):
auto* function_ptr = +[](auto&&... args) to auto* function_ptr = +[]()
return bound(std::forward<decltype(args)>(args)...); to return bound();
Succesfully compiles and runs, although I would have assumed that by using a parameter pack that can be inferred at compile time on a lambda, wouldn't result in that lambda becoming a closure as such (being unconvertable to a function pointer as it requires a context)
I'm ideally trying to achieve:
const auto hook = entry_hook(nullptr, [](auto original, int param1, double param2)
{
// ...
});
Where original is of type void(*)(int, double) and entry_hook can expose a function pointer to the passed in lambda
Reference:
This answer converts a capturing lambda into a function pointer C++ lambda with captures as a function pointer
This answer converts a lambda into a function pointer Obtaining function pointer to lambda?

No: it's impossible.
Because the lambda that you trying to convert to a function pointer
[](auto && ... args) { /* something */ }
is a generic (and variadic; but the point is that is a generic one) lambda.
So is almost as a (variadic) template function (more exactly: as a struct with a variadic template operator() in it) as
template <typename ... As>
SomeRetType func (As && ... as)
{ /* do something */ }
and you can't have a pointer from func()
auto fp = &func; // same problem
because func() isn't an object but a set of objects.

Related

To transform std::bind to std::function?

See the code below
queue<function<void()> > tasks;
void add_job(function<void(void*)> func, void* arg) {
function<void()> f = bind(func, arg)();
tasks.push( f );
}
func is the function I want to add to the tasks which has argument is arg.
How can I do to use std::bind to bind its argument so that it can be assigned to the object of std::function<void()>?
How can I do to use std::bind to bind its argument so that it can be assigned to the object of function<void()>?
The std::bind returns an unspecified callable object, which can be stored in the std::function directly. Therefore you required only
function<void()> f = bind(func, arg); // no need to invoke the callable object
tasks.push( f );
However, I would recommend using lambdas (since C++11) instead of std::bind.
Secondly, having global variables are also not a good practice. I would propose the following example code. Let the compiler deduce the type of the passed functions and their (variadic) arguments (function-template).
template<typename Callable, typename... Args>
void add_job(Callable&& func, Args const&... args)
{
// statically local to the function
static std::queue<std::function<void()>> tasks;
// bind the arguments to the func and push to queue
tasks.push([=] { return func(args...); });
}
void fun1(){}
void fun2(int){}
int main()
{
add_job(&fun1);
add_job(&fun2, 1);
add_job([]{}); // passing lambdas are also possible
}
See a demo in
Just bind it, don't execute it.
function<void()> f = bind(func, arg);
tasks.push( f );

C++ lambda as templated parameter of a function not working

I'm trying to pass a lambda into a parameter in the maybe() function, which is working strangely. Code is below:
template<typename R, typename F>
void maybe(R& result, F& lambda) {
if (0 == result) {
result = lambda();
}
}
auto l = [&]() {
return adi_uart_Open(deviceNum, ADI_UART_DIR_BIDIRECTION, &memory, ADI_UART_BIDIR_DMA_MEMORY_SIZE, &handle);
};
If I call
maybe(result, l);
then everything works just fine. However, if I put the lamba into the function directly, like:
maybe(result, [&](){return adi_uart_Open(deviceNum, ADI_UART_DIR_BIDIRECTION, &memory, ADI_UART_BIDIR_DMA_MEMORY_SIZE, &handle);});
then I get the following error:
error: no instance of function template "maybe" matches the argument list
I'd use std::function instead of templates, but it's not available on the embedded device i'm working on.
maybe takes an lvalue reference:
maybe(R& result, F& lambda)
C++ forbids a non-const lvalue reference to be bound to a temporary. Add a const.
maybe(R& result, F const& lambda)

How to make template deduce return type of function with variadic arguments

Someone on stack overflow wrote an interesting way to capture a lambda or functor into your own class. I was trying to simplify it, and I think I got close but was having some trouble. Their example was:
// OT => Object Type
// RT => Return Type
// A ... => Arguments
template<typename OT, typename RT, typename ... A>
struct lambda_expression {
OT _object;
RT(OT::*_function)(A...)const; // A pointer to a member function,
// specifically the operator()
lambda_expression(const OT & object) // Constructor
: _object(object),
_function(&decltype(_object)::operator()) {} // Assigning the function pointer
RT operator() (A ... args) const {
return (_object.*_function)(args...);
}
};
Basically this allows you to go:
int captureMe = 2;
auto lambda = [=](int a, int b) { return a + b + captureMe;};
lambda_expression<decltype(lambda), int, int, int>(lambda);
I was trying to simplify this, and thought that the pointer contained in the lambda_expression class wouldn't be needed, because you can call the function object itself, instead of calling the pointer to the operator(). So I tried this:
template <typename OT, typename ... Args> // No Return type specified
struct lambdaContainer
{
lambdaContainer(OT funcObj) : funcObj(funcObj){ }
OT funcObj; // No pointer, just the function object.
auto operator()(Args... args)
{
return funcObj(args...); // Call the function object directly
}
};
Then something like:
int captureMe = 2;
auto lambda = [=](int a, int b) { return a + b + captureMe; };
lambdaContainer<decltype(lambda), int, int> lam(lambda);
auto i = lam(1, 1);
// i = 4;
Where I wrote the line:
auto operator()(Args... args)
{
return funcObj(args...);
}
Apparently:
decltype(auto) operator()(Args... args) //works in C++14 apparently.
But I tried without the auto keyword and I failed miserably in doing this, I want to understand how the Args... works. I tried:
decltype(funObj(Args...) operator()(Args... args) // this failed
decltype(OT(Args...) operator() (Args... args) // this failed
auto operator() (Args... args) -> decltype(funcObj(Args...)) // this failed
auto operator() (Args... args) -> decltype(OT(Args...)) // this failed
How can I expand the Args parameter so the template can deduce the return type? Is this only possible with auto?
decltype(e) takes an expression e and evaluates to the type of that expression. You need to provide an expression that represents the invocation of your stored lambda:
auto operator()(Args... args)
-> decltype(std::declval<OT>()(std::declval<Args>()...))
In this case, I'm using std::declval to create a "fake instance" of the objects that can be used for deduction purposes, without actually invoking any constructor.
Let's break this down even further:
-> decltype(
std::declval<OT>() // create a fake instance of `OT`
( // invoke it
std::declval<Args>()... // create a fake instance of each argument
// type, expanding `Args...`
)
)
live example on wandbox
By the way, you should still std::forward the arguments in your call to funcObj as there might be some rvalue references that need to be propagated further down:
auto operator()(Args... args)
{
return funcObj(std::forward<Args>(args)...);
}

Pass lambda to numerical library

I am trying to use a numerical integration library that requires me to pass it a double (*f)(double,void*) as an argument. How can I pass it a lambda I create in the same scope? I tried
auto myLambda = [&](double d, void* data) { ... }
but the type of the lambda cannot be converted to the type required by the library. Is there an workaround?
Thank you for your time!
template<class T>using type=T;
template<class F>
struct callback_t {
F data;
void* pdata(){return &data;}
template<class R, class...Args>
operator type<R(*)(Args...,void*)>()const{
return [](Args...args,void*pdata)->R{
F* data=static_cast<F*>(pdata);
return (*f)(std::forward<Args>(args)...);
};
}
};
template<class F>
callback_t<F> callback(F f){
return{std::move(f)};
}
use:
int scale=3;
auto cb = callback([&](double d){return d*scale;});
then pass cb in place of the function pointer, and cb.pdata() for the void* parameter.
Presumably this library also lets you pass in the data argument with which the supplied function will be called. In that case, you can define a wrapper that treats that argument as a pointer to the actual object you want to call and forwards the call to that object, maybe something like this:
template <class F>
double function_for_library(double d, void* data) {
F& f = *static_cast<F*>(data);
return f(d);
}
Now if you have some arbitrary function object f of type F you can invoke the library like this:
invoke_library(function_for_library<F>, &f); // implicit conversion to void*
For a lambda you'll have to use decltype but it's no big deal.
auto myLambda = /* ... */;
invoke_library(function_for_library<decltype(myLambda)>, &myLambda);
Or you can write another wrapper that deduces the type.
Only lambda without capture may decay to function pointer
I suspect that void* is the way to pass user data.
so you have to create a struct
struct Functor
{
explicit Functor(capture_t&);
void operator()(double d)
{
// Your stuff
}
static void call(double d, void* userdata)
{
(*reinterpret_cast<Functor*>(userdata))(d)
}
private:
capture_t m_capture
};
And then call
Functor func(capture);
library_function(&Functor::call, &func);

C++ templated callback bounce function

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.