Best practice for local variable scope in a C++ callback - c++

I have a functioning C++ callback function, triggered by a user 'mouse down' event. (The IDE is VS2010.)
With each call, I'd like to increment a simple count variable that is local to the callback's scope. Simply put, what is the 'best practices' way to do this?
Thanks in advance for any opinions or directives.

Replace your callback function with a functor - they can store state. An example functor:
#include <iostream>
#include <memory>
class Functor
{
private:
std::shared_ptr<int> m_count;
public:
Functor()
: m_count(new int(0))
{}
void operator()()
{
++(*m_count);
// do other stuff...
}
int count() const
{
return *m_count;
}
};
template <typename F>
void f(F callback)
{
// do stuff
callback();
// do other stuff
}
int main()
{
Functor callback;
f(callback);
f(callback);
std::cout << callback.count(); // prints 2
return 0;
}
Note the use of a shared_ptr inside the functor - this is because f has a local copy of the functor (note the pass-by-value) and you want that copy to share its int with the functor to which you have access. Note also that f has to take its argument by value, since you want to support all callables, and not just functors.

Related

How to remove a std::function<void()> in vector?

I'm trying to create C# event in c++ for my game engine. I'm implementing the event system now but I don't know how to remove a std::function in a vector. Am I using the correct list?
I'm quite new in C++ but I'm a C# programmer for 10 years now. Is this possible in C++?
#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
struct Delegate {
std::vector<std::function<void()>> funcs;
template<class T> void operator+=(T mFunc)
{
funcs.push_back(mFunc);
}
template<class T> void operator-=(T mFunc)
{
// How?
//funcs.erase(std::remove(funcs.begin(), funcs.end(), mFunc), funcs.end());
}
void operator()() {
for (auto& f : funcs) f();
}
};
void fun1()
{
std::cout << "hello, ";
}
void fun2()
{
std::cout << "Delete";
}
void fun3()
{
std::cout << "world!" << std::endl;
}
int main() {
Delegate delegate;
delegate += fun1;
delegate += fun2;
delegate -= fun2;
delegate += fun3;
delegate();
}
If you are willing to limit Delegate to only using function pointers the you can do it with what you have. That would look like
struct Delegate {
std::vector<void(*)()> funcs;
template<class T> void operator+=(T mFunc)
{
funcs.push_back(mFunc);
}
template<class T> void operator-=(T mFunc)
{
funcs.erase(std::remove(funcs.begin(), funcs.end(), mFunc), funcs.end());
}
void operator()() {
for (auto& f : funcs) f();
}
};
If you don't want to do so, then you need to change you approach. You could have operator += return an index to the inserted function, and then you can change operator -= to take that index and remove that element. see eerorika's answer for a suggestion on how to return iterators to the functions.
Is this possible in C++?
Not like this. Function wrappers cannot be compared for equality. This is a limitation in their design.
One option is to use function pointers. They can be compared for equality. But then you cannot use stateful function objects. NathanOliver shows an example of this.
Another alternative design would be to use a std::list as the container, and when ever you register a function, return iterator to it. Then, instead of erasing by passing the function, you can pass the iterator to be erased.
std::function objects are not directly comparable, but if you are only using regular functions (not e.g. member functions or capturing lambdas), you can use target() method to extract underlying pointer.
void operator-=(void(*mFunc)())
{
auto pred = [&mFunc](const std::function<void()>& func) { return mFunc == *func.target<decltype(mFunc)>(); };
funcs.erase(std::remove_if(funcs.begin(), funcs.end(), pred), funcs.end());
}
I changed the type T to be function pointer explicitly, because std::function would need a different approach (calling target() on that too). You can overload your operator -= to handle std::function separately.
It's ugly, but it works.
Note: Above snippet doesn't really take into account type safety. target() will return nullptr if type declared by template does not match the actual type stored by std::function, and dereferencing nullptr will be disastrous. Since your code only seems to deal with free functions of signature void(), it shouldn't be much issue, but if you plan to use lambdas or something it may break.

Passing a lambda with moved capture to function

I recently struggled with a bug hard to find for me. I tried to pass a lambda to a function taking a std::function object. The lambda was capturing a noncopyable object.
I figured out, obviously some copy must happen in between all the passings. I came to this result because I always ended in an error: use of deleted function error.
Here is the code which produces this error:
void call_func(std::function<void()> func)
{
func();
}
int main()
{
std::fstream fs{"test.txt", std::fstream::out};
auto lam = [fs = std::move(fs)] { const_cast<std::fstream&>(fs).close(); };
call_func(lam);
return 0;
}
I solved this by capseling the std::fstream object in an std::shared_ptr object. This is working fine, but I think there may be a more sexy way to do this.
I have two questions now:
Why is this error raising up?
My idea: I generate many fstream objects and lambdas in a for loop, and for each fstream there is one lambda writing to it. So the access to the fstream objects is only done by the lambdas. I want do this for some callback logic. Is there a more pretty way to this with lambdas like I tried?
The error happens because your lambda has non-copyable captures, making the lambda itself not copyable. std::function requires that the wrapped object be copy-constructible.
If you have control over call_func, make it a template:
template<typename T>
void call_func(T&& func)
{
func();
}
int main()
{
std::fstream fs{"test.txt", std::fstream::out};
auto lam = [fs = std::move(fs)] { const_cast<std::fstream&>(fs).close(); };
call_func(lam);
}
Following is my take on your idea in (2). Since std::function requires the wrapped object to be copy-constructible, we can make our own function wrapper that does not have this restriction:
#include <algorithm>
#include <fstream>
#include <iterator>
#include <utility>
#include <memory>
#include <sstream>
#include <vector>
template<typename T>
void call_func(T&& func) {
func();
}
// All functors have a common base, so we will be able to store them in a single container.
struct baseFunctor {
virtual void operator()()=0;
};
// The actual functor is as simple as it gets.
template<typename T>
class functor : public baseFunctor {
T f;
public:
template<typename U>
functor(U&& f)
: f(std::forward<U>(f))
{}
void operator()() override {
f();
}
};
// In C++17 you don't need this: functor's default constructor can already infer T.
template<typename T>
auto makeNewFunctor(T&& v) {
return std::unique_ptr<baseFunctor>(new functor<T>{std::forward<T>(v)});
}
int main() {
// We need to store pointers instead of values, for the virtual function mechanism to behave correctly.
std::vector<std::unique_ptr<baseFunctor>> functors;
// Generate 10 functors writing to 10 different file streams
std::generate_n(std::back_inserter(functors), 10, [](){
static int i=0;
std::ostringstream oss{"test"};
oss << ++i << ".txt";
std::fstream fs{oss.str(), std::fstream::out};
return makeNewFunctor([fs = std::move(fs)] () mutable { fs.close(); });
});
// Execute the functors
for (auto& functor : functors) {
call_func(*functor);
}
}
Note that the overhead from the virtual call is unavoidable: Since you need functors with different behavior stored in the same container, you essentially need polymorphic behavior one way or the other. So you either implement this polymorphism by hand, or use virtual. I prefer the latter.

rebind one parameter of std::function

In my C++ project I decided to give the new++ features a try. One of those features is the binding of a function with std::function via std::bind.
Now I came to a use case, where I have to rebind the std::function.
Consider the following simplified code:
class Test
{
public:
void first()
{
second(bind(&Test::third, this));
}
void second(function<void()> fun)
{
Test *other = new Test();
fun->rebindLastParameter(other); // How can I do this?
fun();
}
void third()
{
// This is called in context of "other"
}
}
How can I do the fun->rebindLastParameter(other); part (replace this pointer with other)?
(EDIT) Context:
In my application there are several classes which inherit from a class called BaseModel. Those classes are automatically transpiled from a self made description language. The following class represents a simple "asteroid" which consists of two other "asteroids":
#pragma once
#include "BaseModel.h"
#include <functional>
using namespace std;
using namespace std::placeholders;
class Test : public BaseModel
{
public:
Test(const OBB& start_obb) : BaseModel(start_obb) {}
void __init() {
scene();
}
void scene() {
combine(bind(&Test::asteroid, this),bind(&Test::asteroid, this));
}
void asteroid() {
translate(random_float(),random_float(),random_float());
sphere(7);
repeat(400,bind(&Test::impact, this));
}
void impact() {
auto p1 = random_surface_point();
select_sphere(p1,random_float() * 2 + 1,1.0);
normalize(p1);
translate_selection(-p1 * random_float() * 0.4);
}
};
The problem lies in the function BaseModel::combine, that combines (via constructive solid geometry) two new objects (1st asteroid and 2nd asteroid):
void BaseModel::combine(function<void()> left, function<void()> right)
{
BaseModel *leftModel = (BaseModel*) ::operator new (sizeof(BaseModel));
BaseModel *rightModel = (BaseModel*) ::operator new (sizeof(BaseModel));
leftModel->initWithStartOBB(*this->obb);
rightModel->initWithStartOBB(*this->obb);
auto newLeft = bind(left, leftModel); // This does not work
auto newRight = bind(right, rightModel); // This does not work
newLeft();
newRight();
// ... CSG stuff
}
As leftModel and rightModel have to be new models of the same class, I need to rebind the first parameter I previously give in my automatically transpiled class Test::scene.
Perhaps I'm on the wrong track. I hope that additional context could explain why I've run into that problem.
As #tobi303 and others have noted, your function signature for the argument of second is too constrained, as it takes a nullary function. There is nothing to rebind - it doesn't take any parameters.
In order to achieve something like it looks like you're trying to do, you need to have the argument of second be less constricted. There are several ways of doing so (making it take a function, or a pointer to a member function); the following shows it template-parameterized by a function that takes a unary argument:
#include <functional>
using namespace std;
class Test
{
public:
void first()
{
second([](Test *p){p->third();});
}
template<class Fn>
void second(Fn fn)
{
Test *const other = new Test();
fn(other);
}
void third()
{
// This is called in context of "other"
}
};
int main()
{
Test t;
t.first();
}
Personal viewpoint (one that earned me several downvotes): I think the use of many libraries and techniques, most cases of bind for sure, most cases of function - simply precede current lambda functions, and there is less and less of a need for them.
How can I do the fun->rebindLastParameter(other); part (replace this pointer with other)?
You can't, in general.
std::function relies on type-erasure which means the original type of the object that was stored in the std::function is not part of the type, and not easily accessible.
If you know for certain that the fun definitely stores an object returned by bind(&Test::third, this) then there's no need to rebind the argument, just modify fun to hold a completely different function object with the right argument, i.e.
fun = bind(&Test::third, other);
If you know it definitely stores an object returned by bind( &Test::???, other) where &Test::??? is any member function with exactly the same signature as Test::third then you could do something like this:
using binder_type = decltype(bind(&Test::third, this));
if (auto target = fun.target<binder_type>())
{
// *target is the result of the bind() expression
}
But there's still no way to modify the object at *target to replace the Test* pointer it holds.
If you know the set of functions that could have been used then you could do:
using binder_foo_type = decltype(bind(&Test::foo, this));
using binder_bar_type = decltype(bind(&Test::bar, this));
using binder_baz_type = decltype(bind(&Test::baz, this));
if (fun.target<binder_foo_type>())
{
fun = std::bind(&Test::foo, other);
}
else if (fun.target<binder_bar_type>())
{
fun = std::bind(&Test::bar, other);
}
else if (fun.target<binder_baz_type>())
{
fun = std::bind(&Test::baz, other);
}
But these are not general purpose solutions and not very maintainable.
std::mem_fn is what you are looking for, as it generates wrapper objects for pointers to members.
std::function<void(Test*)> f = std::mem_fn(&Test::third);
f(this);
Test *other = new Test();
f(other);
With std::bind, use fun with a reference to Test object. This way you can call it with a new object
void second(std::function<void(const Test&)> fun)
{
Test *other = new Test();
fun(*other);
}
Or with this object
fun(*this);

Missing call to bound pointer to member function

I am trying to implement a generic event handling system with templates, but I get an error at compile time when I try to add the function to a list.
error C2298: missing call to bound pointer to member function
class EventManager
{
public:
template <class OBJECT>
void subscribe(std::string eventName, OBJECT *obj, void(OBJECT::*newEvent)(Event))
{
(obj->*newEvent)(Event()); // I can call the event just fine if I execute it alone
abc.push_back(obj->*newEvent); // Error c2298 here
}
static EventManager* Get();
private:
std::vector<void(*)(Event)> eventsList;
};
And this is where I call it:
EventManager::Get()->subscribe("EventName", this, &TestClass::eventTest);
void ATideManager::eventTest(Event event)
{
//Test
}
I am quite new to C++ and templates, so I'm sure the solution is easy, but I don't understand why I can call the event but not add it to the vector. Do you know how I could possibly do that?
As the documentation for that error message says:
A pointer to member-function expression must call the member function.
In other words, you cannot store a pointer to member-function including the object on which to call it, for later use.
Here is a simpler example using names similar to yours:
struct Object
{
void f() {}
};
int main()
{
Object obj;
using member_function_pointer = void (Object::*)();
member_function_pointer ptr = &Object::f;
(obj.*ptr)();
(obj.*ptr); // error
}
And this makes a lot of sense. Your abc is probably a vector of pointers to member-function (or just a vector of function pointers); it cannot magically store an object along with each pointer in it.
Generally, pointers to member functions are not exactly the nicest, cleanest or best feature of C++, and the awful syntax renders every piece of code using it completely unreadable. Fortunately, C++11 introduced std::function and lambdas, which gives you a much better alternative:
#include <functional>
#include <iostream>
#include <string>
#include <vector>
struct Event
{
int i;
};
class EventManager
{
public:
void subscribe(std::string const& eventName,
std::function<void(Event const&)> event)
{
abc.push_back(event);
}
static EventManager& get()
{
static EventManager instance;
return instance;
}
void onEvent(Event const& event)
{
for (auto&& f : abc)
{
f(event);
}
}
private:
EventManager() {}
EventManager(EventManager const&) = delete;
EventManager& operator=(EventManager const&) = delete;
std::vector<std::function<void(Event const&)>> abc;
};
struct ATideManager
{
void f()
{
EventManager::get().subscribe("EventName",
[=](Event const& event) { eventTest(event); });
}
void eventTest(Event const& event)
{
std::cout << "eventTest: " << event.i << "\n";
}
};
int main()
{
ATideManager manager;
manager.f();
Event some_event{ 123 };
EventManager::get().onEvent(some_event);
}
I've also fixed your needless use of pointers where references can be used, and some const-correctness issues.
obj->*newEvent is invalid. A member function pointer can be used in this way only to call the pointed-to member function.
You can however use std::vector<std::function<void(Event)>> and
abc.push_back(std::bind(newEvent, obj, std::placeholders::_1);
std::bind reference

generic c++11 function wrapper for task based parallelism

I am implementing a work stealing algorithm and am writing a generic function wrapper that takes a promise as one of the variadic arguments to the wrapper template. I want to create tasks with these function wrappers and get each node to communicate to dependent nodes using promises. Each node maintains a list of dependent nodes and promises/futures. Each node can run by checking if all futures have been set. promises can vary depending on the job the function wrapper is doing returning different objects. If a single algorithm can be broken into separate operations like read message and decode message, perform checks on object, return result of all checks, each of these actions will return a different promise (object, boolean, result).
The book, C++ Concurrency in Action, has a function wrapper implementation however, that doesn't handle this use case. In other references online, I've seen hardcoded references to promises like std::promise which is only one type.
Can someone advise how I can write a wrapper to achieve the following...
void add(int a, int b, std::promise<int>&& prms)
{
int res = a + b;
try {
prms.set_value(res);
}
catch(...)
{
prms.set_exception(std::current_exception());
}
}
int main()
{
std::promise<int> prms;
std::future<int> fut = prms.get_future();
FunctionWrapper myFunctor(a, 10, 20, std::move(prms));
// add the functor to the queue and it will be retrieved by a thread
// that executes the task. since i have the future, i can pass it to the
// dependent worknode
}
I tried writing the code like below...but was facing difficulties in getting this to work.
#ifndef FUNCTIONWRAPPER_HPP
#define FUNCTIONWRAPPER_HPP
template<typename F, typename R, typename... Args>
class FunctionWrapper
{
class implbase
{
public:
virtual ~implbase();
virtual R execute(Args...)=0;
};
class impl : public implbase
{
public:
impl(F&& f) : func(std::move(f)) {}
virtual R execute(Args... args) { return func(args...); }
private:
F func;
};
std::shared_ptr<impl> internalFunc;
public:
FunctionWrapper(F&& f) : internalFunc(0)
{
internalFunc = new impl<F, R, Args...>(f);
}
FunctionWrapper(const FunctionWrapper& other)
: internalFunc(std::move(other.internalFunc))
{}
~FunctionWrapper()
{
if(internalFunc)
delete internalFunc;
}
R operator()(Args... args)
{
return internalFunc->execute(args...);
}
void swap(FunctionWrapper& other)
{
impl<R, Args...>* tmp = internalFunc;
internalFunc = other.internalFunc;
other.internalFunc = tmp;
}
FunctionWrapper& operator=(const FunctionWrapper& other)
{
FunctionWrapper(other).swap(*this);
return *this;
}
FunctionWrapper& operator=(const F& f)
{
FunctionWrapper(f).swap(*this);
return *this;
}
};
#endif // FUNCTIONWRAPPER_HPP
C++11 has a wrapper for doing just this! It is called packaged_task.
What it does, is it wraps a callable object (function objects, lambdas, function pointers, bind expressions, etc...) and provides you a future via the get_future() method that matches the return type of the function passed in.
Consider the following example:
#include <thread>
#include <future>
#include <functional>
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int main()
{
// Create a std::packaged_task and grab the future out of it.
packaged_task<int()> myTask(bind(add, 10, 20));
future<int> myFuture = myTask.get_future();
// Here, is where you would queue up the task in your example.
// I'll launch it on another thread just to demonstrate how.
thread myThread(std::move(myTask));
myThread.detach();
// myFuture.get() will block until the task completes.
// ...or throw if the task throws an exception.
cout << "The result is: " << myFuture.get() << endl;
return 0;
}
As you can see, rather than passing in a promise, we are counting on the packaged_task to create the promise and give us the future.
Also, using a bind expression has allowed us to effectively hand arguments to the task to hold onto until it is called.
Using packaged_task also puts the burden pushing exceptions through the future into the hands of the packaged_task. That way, your functions do not need to call set_exception(). They only have to return or throw.