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.
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);