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 );
Related
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.
Following on from this question: can-a-temperary-lambda-by-passed-by-reference?
I have a fixed code snippet:
// global variable
std::thread worker_thread;
// Template function
template <typename Functor>
void start_work(const Functor &worker_fn) // lambda passed by const ref
{
worker_thread = std::thread([&](){
worker_fn();
});
}
This is called like this:
void do_work(int value)
{
printf("Hello from worker\r\n");
}
int main()
{
// This lambda is a temporary variable...
start_work([](int value){ do_work(value) });
}
This seems to work, but I am concerned about passing a temporary lambda into the thread constructor since the thread will run, but the function start_work() will return and the temp-lambda will go out of scope.
However I was looking at the std::thread constructor which is defined:
thread() noexcept; (1) (since C++11)
thread( thread&& other ) noexcept; (2) (since C++11)
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args ); (3) (since C++11)
thread(const thread&) = delete; (4) (since C++11)
So I am assuming that the constructor 3 is called:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
I struggle to understand what is written here, but it looks like it would try to move the lambda && which I believe is ok for temp variables.
So is what I have done in my code snippet dangerous (i.e. the ref goes out of scope) or correct (i.e. the temp is moved and all is well)? or neither??
An alternative is to just pass my value (make a copy) which is not so bad anyway in this case.
A temporary is indeed moved but it is the "inner" one, the argument to std::thread.
That temporary holds a reference to the "outer" temporary, the argument to start_work, and whose lifetime ends after start_work has returned.
Thus, your "inner" lambda object holds a reference to an object that may or may not exist during its execution, which is very unsafe.
A lambda is an anonymous struct in C++. If we were to translate the snippet to an equivalent one without lambdas, it would become
template <typename Functor>
void start_work(const Functor &worker_fn)
{
struct lambda {
const Functor& worker_fn;
auto operator()() const { worker_fn(); }
};
worker_thread = std::thread(lambda{worker_fn});
}
lambda has a non-stack-based const reference as a member, which would dangle as soon as start_work returns, regardless whether the lambda object itself is copied.
When passing the arguments to std::bind they are always copied or moved, unless wrapped by std::ref and I want to do the same with a lambda expression.
The Problem is, that I want to wrap the generation of the lambda expression in a function and forward the arguments as passed by the user to the lambda. The reason I want to do this, is that I want to call the lambda asynchronously and let the user decide if the arguments shall be passed by reference or by copy.
Consider the following example. I have the function print_address that takes the parameter as reference. Then I have the function combine_and_call_bind that forwards the arguments into std::bind.
void print_address(int& a) {
std::cout << "Adress of a = " << &a << std::endl;
}
template<typename F, typename Args>
void combine_and_call_bind(F f, Args&& args) {
auto a = std::bind(f, std::forward<Args>(args));
a();
}
The user can the specify when calling the combine_and_call_bind-function if the arguments shall be copied into std::bind or if they shall be passed by reference by wrapping the arguments in std::ref:
combine_and_call_bind(print_address, a); // copy a into std::bind
combine_and_call_bind(print_address, std::ref(a)); // pass a as reference into std::bind
How can I do the same with the following function combine_and_call_lambda, while using C++11?
template<typename F, typename Args>
void combine_and_call_lambda(F f, Args&& args) {
auto a = [/* std::forward<Args>(args) */, f] {
f(args);
};
a();
}
You might try to capture everything by value:
template<typename F, typename... Args>
void combine_and_call_lambda(F f, Args&&... args) {
auto a = [=]() mutable {
f(args...);
};
a();
}
Then use:
combine_and_call_lambda(print_address, a);
combine_and_call_lambda(print_address, std::ref(a));
DEMO
As we can see at lambda:
captures - a comma-separated list of zero or more captures, optionally
beginning with a capture-default.
Capture list can be passed as follows (see below for the detailed
description):
...
[=] captures all automatic variables used in the body of the lambda
by copy and current object by reference if exists
So, in the code above everything is copied and stored inside the lambda object.
So I'm trying to create a class which has a container for functors of a different type.
This is a simplified version of it.
template<class T>
class Container
{
public:
template<typename F, typename ... ARGS>
void addTask(F && func, ARGS && ... args);
private:
std::deque<std::function<T()>> container;
//.....
};
template<class T>
template<typename F, typename ... ARGS>
T Container<T>::addTask(F && func, ARGS && ... args);
{
container.emplace_back(std::bind(f,args...));
//.....
}
There are still few problems that I cannot solve yet.
Is there a way to remove std::bind and store a different object or a pointer?
Could this be more generic? Can I somehow store functions, which return different objects, in a single container(int,void...)?
Can some of the logic for creating the tasks be executed in compile time?Something like consexpr bind.
From a comment by the OP.
There are. This is simplified. I'm using futures and a special container in the real code. It is meant to be used in a multithreading environment
This is called burying the lede.
If you are storing callables to be invoked in other threads, in the other thread you want signature void(). In this thread you want a std::future to be populated.
As for binding arguments, while a number of std functions do this for you, I find it is best to ask for callables with pre-bound arguments. They can do it outside, using std::bind or lambdas or whatever other means they choose.
So this then comes
template<class Func,
class R = std::decay_t<std::result_of_t<Func const&()>>
>
std::future< R >
addTask( Func&& func ) {
auto task = std::packaged_task<R()>(std::forward<Func>(func));
auto ret = task.get_future();
container.push_back( std::packaged_task<void()>( std::move(task) ) );
return ret;
}
std::deque< std::packaged_task<void()> > container;
throw in some mutexes and shake and bake.
Here I use std::packaged_task<void()> as a pre-written move-only type-erased container for anything with that signature. We don't use the future it can produce, which is a waste, but it is shorter than writing your own move-only invoke-once owning function object.
I personally just wrote myself a light weight move-only std::function<void()> esque class instead of using std::packaged_task<void()>, but it was probably unwise.
The future returned from addTask gets fullfilled when the packaged_task<R()> is invoked, which is invoked when the packaged_task<void()> is invoked (possibly in another thread).
Outside of the structure, callers can give you any zero-argument callable object.
99 times out of 100, a simple [some_arg]{ some_code; } or even []{ some_code; } works. In complex cases they can mess around with std::bind or C++14 improvements with more complex lambdas.
Putting the storing of the arguments into addTask mixes the responsibility of the thread-task-queue with messing with arguments.
In fact, I'd write a thread-safe queue separately from my thread-pool, and have the thread-pool use it:
template<class T>
struct thread_safe_queue;
struct thread_pool {
thread_safe_queue< std::packaged_task<void()> > queue;
// etc
};
In C++17, a replacement for your bind looks like:
[
func = std::forward<Func>(func),
args = std::make_tuple( std::forward<Args>(args)... )
]() mutable {
std::apply( func, std::move(args) );
}
In C++14 you can write notstd::apply pretty easy. Move-into-lambda requires C++14, so if you need to efficiently move arguments you need std bind or a manual function object in C++11.
I will argue that placing the argument binding strongly in the domain of the code using the thread pool is best.
That also permits the thread pool to do things like pass the tasks optional extra arguments, like "cancellation tokens" or the like.
std::bind came from boost::bind, which was necessary before we had lambdas.
Unfortunately std::bind made it into the standard at the same time as lambdas, so it was immediately almost irrelevant.
In c++14 and beyond you can capture the function and args in a variadic lambda:
template<class T>
template<typename F, typename ... ARGS>
T Container<T>::addTask(F && func, ARGS && ... args)
{
container.emplace_back( [func = std::forward<F>(func),
args...]
() mutable // make mutable if you want to move the args in to func
{
return func(std::move(args)...);
});
//.....
}
You don't quite get perfect forwarding this way. There is a copy implicit in the capture of args...
This solved in c++17
template<class T>
template<typename F, typename ... ARGS>
T Container<T>::addTask(F && func, ARGS && ... args)
{
container.emplace_back( [func = std::forward<F>(func),
args = std::make_tuple(std::forward<ARGS>(args)...) ]
() mutable // make mutable if you want to move the args in to func
{
return std::apply(func, std::move(args));
});
//.....
}
I'm trying to mimic std::thread constructor functionality:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
I've tried stepping with debugger to see how it works but I couldn't figure it out.
How can I create and store bind type like thread's constructor does ?
Something like this (the syntax maybe wrong):
class myClass{
private:
auto bindType;
public:
template< class Function, class... Args >
explicit myClass( Function&& f, Args&&... args ) : bindType(somehowBind(f, args) {}
void evaluate() {bindType();}
};
Example of usage:
int test(int i) {return i;}
int main(){
myClass my(test, 5);
my.evaluate();
}
Note that I don't care if somehowBind function will ignore the return type i.e. its return type can be something like std::function.
All I wan't to do is understand how I can bind class... Args to a given function f such that after calling somehowBind it will act like std::bind does.
To clarify my point you can think about what I'm trying to achieve as follow:
thread t(test, 5); // unlike the usual std:::thread, this one is created in suspended mode therefore I need somehow to bind `f` with `5` and store it
t.start(); // now t is executed
It's kinda reminds C# and Java threads, they not executed right after construction.
For starters, to bind some parameters to a function using std::bind you simpy do:
// Some function.
void printValues(int x, double y) {
std::cout << x << " " << y << std::endl;
}
auto func = std::bind(printValues, 5, 2.0); // Bind params and return functor.
func(); // Evaluate function call (returns void in this case).
Next, to store a functor and its parameters in a class and you don't care about the return value when evaluating then simply use a lambda expression to wrap the std::bind expression (the lambda is used to drop the return value):
struct Foo {
template <typename Function, typename... Args>
Foo(Function&& func, Args&&... args) {
auto f = std::bind(std::forward<Function>(func), std::forward<Args>(args)...);
func_ = [f] { f(); };
// func_ = [f{std::move(f)}] { f(); }; // In C++14 you can move capture.
}
void evaluate() { func_(); }
std::function<void()> func_;
};
Also see this live example
If you're looking to store a variadic pack then see this answer: How to store variadic template arguments?