Reputation: 93
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));
}
Upvotes: 2
Views: 105
Reputation: 855
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
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.
Upvotes: 1
Reputation: 518
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?
Upvotes: 0