I was imagining a scenario, where I have a class which behaves as usual, but has some empty (member) function declared, which can be used (similar to overloading) as per needed. Is that possible? How can one achieve it?
To make myself clear, let's say I have a class which utilizes a given input function f at construction at some point (via the process member function below)
class A {
// constructor
A(const Graph& g,
std::function<void(void*)> f = [](void*){ } ) {
...
}
// member functions
...
private:
// member variables
...
// private member functions
void process(void); // This function will utilize the input function f
};
Now, what I can do is to specify the function f in the constructor for A and that will be utilized at the time of processing an instant of A. Using lambda function does this job. However, I wish f to be able to use As private members, as if it was part of As definition. Can it be done?
Thanks in advance,
Nikhil
Have f take reference to A as a parameter. Instead of f acessing A's private members, provide public getters and setters.
class A {
public:
A (const Graph& g, std::function <void (void*, A&)> f)
: f_(f)
{}
// getters and setters
private:
std::function<void (void*, A&)> f_;
void process () {
f_(nullptr, *this);
}
};
The basic technique is to make f accept parameters of the correct types (of A's private members) that it will be working on, and then pass those arguments to f inside the process() function. If there are many, then you'll want to break f up into smaller functions, and make process() call these smaller functions (and, of course, pass in the smaller functions in the constructor).
I'm not sure this is what you're after but I wrote a little example that might be along your lines. Make privatestuff a struct to store private variables in and you can send all the data in one go.
#include <functional>
#include <iostream>
using namespace std;
typedef std::function<void(void*)> DoStuffFunc;
class A
{
public:
A(DoStuffFunc func) {
doStuff = func;
privateStuff = 5;
}
void process() {
doStuff((void*)&privateStuff);
}
private:
int privateStuff;
DoStuffFunc doStuff;
};
void doStuffX(void* data) {
int x = *(int*)data;
cout <<"x: " <<x <<endl;
}
int main(int argc, char** argv) {
DoStuffFunc fX = doStuffX;
A ax(fX);
ax.process();
}
Related
I'd like to have child classes register callbacks to their parent class so that users of the parent class can call methods of the child with a known function signature.
typedef int(*Func)(int);
class A
{
public:
void registerFunc(Func f)
{}
};
class B : public A
{
public:
B()
{
A::registerFunc(&B::myF);
}
int myF(int x) {
// do stuff with member variables
return 3;
}
};
But I get this compiler error
main.cpp:18:23: error: cannot initialize a parameter of type 'Func' (aka 'int (*)(int)') with an rvalue of type 'int (B::*)(int)'
A::registerFunc(&B::myF);
^~~~~~~
main.cpp:8:28: note: passing argument to parameter 'f' here
void registerFunc(Func f)
Here's a Repl illustrating the error in a concise example.
https://replit.com/#Carpetfizz/RudeSmoothComments#main.cpp
The accepted answer in a related thread suggested to override a virtual function declared in A but my use case actually requires dynamic callback registrations.
You can try this.
typedef std::function<int (int)> Func;
class A
{
public:
void registerFunc(Func f)
{}
};
class B : public A
{
public:
B()
{
A::registerFunc(std::bind(&B::myF, *this, std::placeholders::_1));
}
int myF(int x) {
// do stuff with member variables
return 3;
}
};
If I understand the goal (and believe me, that's a sketchy 'if'), you want to specify some member of some A derivation to invoke from some A member as a dispatched 'callback' mechanic. If that is the case, then to answer your question in comment, yes, a function and bind can do this. It can even be semi-protected with a little help from sfinae:
Example
#include <iostream>
#include <type_traits>
#include <functional>
#include <memory>
struct A
{
virtual ~A() = default;
std::function<void(int)> callback = [](int){};
template<class Derived>
std::enable_if_t<std::is_base_of<A, Derived>::value>
registerCallback(void (Derived::*pfn)(int))
{
using namespace std::placeholders;
callback = std::bind(pfn, dynamic_cast<Derived*>(this), _1);
}
void fire(int arg)
{
callback(arg);
}
};
struct B : public A
{
void memberfn(int arg)
{
std::cout << __PRETTY_FUNCTION__ << ':' << arg << '\n';
}
};
struct Foo
{
void memberfn(int arg)
{
std::cout << __PRETTY_FUNCTION__ << ':' << arg << '\n';
}
};
int main()
{
std::unique_ptr<A> ptr = std::make_unique<B>();
ptr->registerCallback(&B::memberfn);
// ptr->registerCallback(&Foo::memberfn); // WILL NOT WORK
ptr->fire(42);
}
Output
void B::memberfn(int):42
The Parts
The first part is straight forward. We declare a member variable callback to be a std::function<void(int)> instance. This is where we'll eventually bind our callable object point. The default value is a lambda that does nothing.
The second part is... a little more complicated:
template<class Derived>
std::enable_if_t<std::is_base_of<A, Derived>::value>
registerCallback(void (Derived::*pfn)(int))
This declares registerCallback as an available member function that accepts a non-static member function pointer taking one int as an argument, but only if the class hosting that member function, or a derivative therein, is a derivation of A (or A itself). Some non-A derivative Foo with a member void foo(int) will not compile.
Next, the setup to the callback itself.
using namespace std::placeholders;
callback = std::bind(pfn, dymamic_cast<Derived*>(this), _1);
This just binds the pointer-to-member to this dynamic-cast to the derivation type (which had better work or we're in trouble, see final warning at the end of this diatribe), and sets the call-time placeholder. The _1 you see comes from the std::placeholders namespace, and is used to delay providing an argument to the callback until such time as we actually invoke it (where it will be required,and you'll see that later). See std::placehholders for more information.
Finally, the fire member, which does this:
void fire(int arg)
{
callback(arg);
}
This invokes the registered function object with the provided argument. Both the member function and this are already wired into the object. The argument arg is used to fill in the placeholder we mentioned earlier.
The test driver for this is straightforward:
int main()
{
std::unique_ptr<A> ptr = std::make_unique<B>();
ptr->registerCallback(&B::memberfn);
// ptr->registerCallback(&Foo::memberfn); // WILL NOT WORK
ptr->fire(42);
}
This creates a new B, hosting it in a dynamic A pointer (so you know there is no funny business going on). Even with that, because B derived from A the registerCallback sfinae filtering passes inspection and the callback is registered successfully. We then invoke the fire method, passing our int argument 42, which will be sent to the callback, etc.
Warning: With great power comes great responsibility
Even those there is protection from passing non-A derived member functions, there is absolutely none from the casting itself. It would be trivial to craft a basic A, pass a B member (which will work since A is its base), but there is no B actually present.
You can catch this at runtime via that dynamic_cast, which we're currently not error checking. For example:
registerCallback(void (Derived::*pfn)(int))
{
using namespace std::placeholders;
Derived *p = dynamic_cast<Derived*>(this);
if (p)
callback = std::bind(pfn, p, _1);
}
You can choose the road more risky. Personally, i'd detect the null case and throw an exception just to be safe(er)
I've checked someone's code through a tool, and it said that there is a problem here:
policyCallback = callback;
I cannot find the problem since I'm a beginner.
Could you give me a hint or guide to translate it?
The entire code is below.
std::function <void (std::vector<std::string> resources)> policyCallback;
namepace nsp {
class Manager {
public:
Manager(const std::string &str);
virtual ~Manager();
template <typename FuncType>
void registerPolicyActionCallback(FuncType callback) {
policyCallback = callback;
}
};
} //namespace nsp
namespace nsp{
class Manager;
}
class SomeAPIs {
public:
void policyActionCallback(std::vector<std::string> param);
};
int main() {
nsp::Manager *rManager;
rManager->registerPolicyActionCallback(std::bind(&SomeAPIs::policyActionCallback, this, std::placeholders::_1));
}
Besides some obvious errors in the code, the main problem preventing you from achieving what you want is the way in which you are calling std::bind.
Firstly, your code declares policyActionCallback(/*...*/) private in SomeAPIs. Now while you can call any member function via a pointer to it, regardless of it being public, protected, or private, only members and friends can create a pointer to a private member function. So unless you call std:bind from within the API itself, or a friend of the API, you will only be able to bind to public member functions of the API. For the sake of demonstrating a working concept, I will assume that the functions you want to use for callback are all public members of the API.
Secondly, to bind a member function using std::bind, you need to provide a reference to the function (which you did), as well a reference (or pointer) to an instance of the class to which the member belongs, which you have not done.
Therefore, since the function you want to bind to is a member of SomeAPIs, you need to give a reference to an instance of SomeAPIs. I'm assuming that you intended this to be a pointer to the nsp::Manager instance, which, as I have just explained, is the wrong object to provide a reference to.
Additionally, your use of the this keyword is incorrect. Taken from cppreference, this can appear in the following contexts
Within the body of any non-static member function, including
member initializer list
Within the declaration of a non-static
member function anywhere after the (optional) cv-qualifier sequence,
including dynamic exception specification(deprecated), noexcept
specification(C++11), and the trailing return type(since C++11)
Within default member initializer (since C++11)
Since your use of this fits non of the above, the compiler gives:
error: invalid use of 'this' in non-member function
Here is working code for what you are wanting to achieve. Note how std::bind is now used. (I have added a constructor for Manager, removed the virtual destructor since manager does not have any virtual function, made the function in SomeAPIs public so that std::bind can receive a pointer to it, and deleted the nsp::Manager pointer which now is declared on the free store):
#include <vector>
#include <iostream>
#include <functional>
std::function <void (std::vector<std::string> resources)> policyCallback;
namespace nsp {
class Manager {
public:
Manager() {};
Manager(const std::string &str) {}
// Don't know why this is virtual when this isn't a base class?
// virtual ~Manager();
template <typename FuncType>
void registerPolicyActionCallback(const FuncType callback) {
policyCallback = callback;
}
};
} //namespace nsp
class SomeAPIs {
public:
void policyActionCallback(std::vector<std::string> param) {
for (const auto& p : param) {
std::cout << "SomeAPIs : " << p << "\n";
}
}
};
// Another API for illustration
class SomeOtherAPI {
public:
void policyActionCallback(std::vector<std::string> param) {
for (const auto& p : param) {
std::cout << "SomeOtherAPI : " << p << "\n";
}
}
};
int main() {
// Sample resource vector for demonstration
std::vector<std::string> resources = {"one", "two", "three"};
// Gets rid of uninitialization error -- alternatively declare on stack
nsp::Manager* rManager = new nsp::Manager;
// You need instances of an object to bind to member functions
SomeAPIs api1;
SomeOtherAPI api2;
// Use the first APIs function as callback
rManager->registerPolicyActionCallback(std::bind(&SomeAPIs::policyActionCallback, &api1, std::placeholders::_1));
policyCallback(resources);
// Use the second APIs function as callback
rManager->registerPolicyActionCallback(std::bind(&SomeOtherAPI::policyActionCallback, &api2, std::placeholders::_1));
policyCallback(resources);
delete rManager;
}
Here is a live demo.
The snippet you provided is badly extracted copy. It confuses because the line resourceManager->registerUMSPolicyActionCallback(std::bind(&SomeAPIs::policyActionCallback, this, std::placeholders::_1)); has argument value this, it means it was called inside of a class. There should be pointer to instance of SomeAPIs.
What i meant in the comment is declaration of method registerPolicyActionCallback. It is not necessary to be a template when policyCallback cannot be anything but the only type std::function <void (std::vector<std::string> resources)>;
Anyway all the code looks good. You wrote you used tool to check code, what tool? Does it supports C++11 properly?
I need to get a member function called by a standard function pointer, so I tried to abstract things like this:
class Sample {
public:
virtual void doSomething(void) = 0;
};
class A : public Sample {
void doSomething(void); // details omitted
};
class B : public Sample {
void doSomething(void); // details omitted
};
class Executor {
public:
Executor(Sample *sample)
: func(&sample->doSomething)
{
}
static void *execute(void *data) {
Executor *pX = data;
(pX->*func)(); // error invalid access of func from static function
(pX->*pX->func)(); // error pointer to member type 'void (Sample::)()'
// incompatible with object type 'Executor'
}
private:
void (Sample::*func)(void);
};
int main(void) {
A myA;
B myB;
Executor x0(&myA);
Executor x1(&myB);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
externallyInvoke is a Linux system call, which takes a function pointer and a data pointer.
I'd like to use a static member function together with a this-pointer as data.
... and I don't want classes like A or B to have static members. So my idea was to create an interface like class Sample, that gets extended by A and B.
My problem is that I don't know how to invoke the pointer to member function from inside the Executor::execute function.
The problem is that you need two objects inside execute - one is the instance of Executor which will supply func, and the other is an instance of (a class derived from) Sample on which func will be invoked. So you have to store the object inside Executor, not the function:
class Executor {
public:
Executor(Sample *sample)
: obj(sample)
{
}
static void *execute(void *data) {
Executor *pX = static_cast<Executor*>(data);
pX->obj->doSomething();
}
private:
Sample *obj;
};
int main() { // note that `void main()` is not legal C++
A myA;
B myB;
Executor x0(&myA);
Executor x1(&myB);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
A pointer to member function (such as your original void (Sample::*func)()) identifies a function within a class, but does not store the object. You'd still need to provide one to call the function.
If you want to interact with an external system call, you basically have to reinvent std::function yourself. No problem, here at Stack Overflow we're the masters of reinventing existing technology. So...
First, the interface:
struct FunctionStateBase
{
virtual ~FunctionStateBase() {}
virtual void Invoke() = 0;
};
extern "C" void InvokeAndDelete(void * data)
{
auto state = static_cast<FunctionStateBase *>(data);
state->Invoke();
delete state;
}
Here's how you use it:
externallyInvoke(&InvokeAndDelete, MakeFunction(&A::doSomething, &myA));
Now we need to implement MakeFunction:
template <typename> struct FunctionState;
template <typename C, typename R>
struct FunctionState<R (C::*)()> : FunctionStateBase
{
R (C::ptmf_*)();
C * obj_;
FunctionState(R (C::ptmf*)(), C * obj) : obj_(obj), ptmf_(ptmf) {}
virtual void Invoke() { (C->ptmf_)(); }
};
template <typename C, typename R>
FunctionState<R (C::*)()> MakeFunction(R (C::*ptmf)(), C * obj)
{
return new FunctionState<R (C::*)()>(ptfm, obj);
}
At this point we're managing the life time of the function wrapper manually, and note that InvokeAndDelete actually takes ownership of the function state. In proper C++, we would wrap the entire system call invocation in a class that would encapsulate the lifetime management internally.
You can add further specializations for member functions that take arguments; you just need to store a copy of the arguments in the state.
You'll need to also pass an instance ofSample on which to call the function (since it's a pointer to a member of Sample). There's a few ways to bring the instance along. You could make it a member of Executor, pass a std::pair* as data or you could combine the function pointer and the instance as a functor. Here's a lamda based approach for the latter. Lamda has the advantage of being more versatile. It's possible to do much more than just call one member of one class. As a bonus, this approach does not avoid visibility rules, although that means doSomething may not be private (or it must be called through the parent pointer).
template<class F>
class Executor {
F f;
public:
Executor(F f): f(f){}
static void *execute(void *data) {
Executor<F> *pX = static_cast<Executor<F>*>(data);
pX->f();
return this; // not quite sure what you intend to return, but just to make this a well formed function...
}
};
int main() {
A myA;
B myB;
auto callback0 = [myA]{
myA.doSomething();
};
auto callback1 = [myB]{
myB.doSomething();
};
Executor<decltype(callback0)> x0(callback0);
Executor<decltype(callback1)> x1(callback1);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
I am writing a wrapper for a multithreaded scheme. It should operate similar to a timer.
I have a particular class (clock) that implements a function called tick which should be passed to constructor. How do I describe a C++ style function (myClass::myfunction, as opposed to the C convention) as the parameter to a method or constructor?
Would anybody be kind enough to show me the declaration for this kind of constructor?
clock myInstance(otherClass::aMethod)
myInstance.tick(); // Should call otherClass::aMethod
myInstance.tick();
Does C++11 and Bind help?
You can either call a static member function of a class or a non-static member function of an object. A non-static member function needs to have the context of an object (this pointer).
Here's a simplified example of how you can use functors and bind to call a member function.
#include <functional>
class clock
{
public:
clock(const std::function<void()>& tocall) : m_tocall(tocall) {}
void tick() {m_tocall();}
private:
std::function<void()> m_tocall;
};
class otherclass
{
public:
void aMethod() {}
};
int main(int argc, char *argv[])
{
otherclass A;
clock c( std::bind(&otherclass::aMethod, &A) );
c.tick(); // Will end up calling aMethod() of object A
}
You need not to use std::function for this. You need to have TWO pointers: One is the class-object, and one to the method of that class. In simple terms, you need to make it able to do:
CallNonVirtual(pClassPtr, pFuncAddr);
And therefore, you need both parameters, so that you can actually call it like:
(pClassPtr->*pFuncAddr)(); // Assuming no parameter
For this, you can do:
class Clock
{
COtherClass* pClassPtr;
/// Typedef simplifies
typedef void (COtherClass::*TargetFuncType)();
TargetFuncType pFuncAddr;
public:
Clock(COtherClass* pOther, TargetFuncType pFunc) :
pClassPtr(pOther), pFuncAddr(pFunc)
{
}
void tick()
{
(pClassPtr->*pFuncAddr)();
}
};
And make a call:
int main()
{
COtherClass Obj;
Clock theClock(&Obj, &COtherClass::TheNonStatic);
theClock.tick();
}
I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...