Check if method is invokable in Qt - c++

My Qt5/C++ program creates a method name (string) on the fly and then if the method is invokable will call it (using invokemethod). And if not invokable/does not exist, then it will no attempt to invoke it. My methods would be defined like this:
Q_INVOKABLE void m1();
void m2();
Q_INVOKABLE void m3();
So m1 and m3 would be directly invokable using "invokemethod". But m2 would not. Since my code will determine on the fly which method to invoke (creating a string with the method name), I need to test if a method is invokable at runtime. How can I do that? I want something like:
bool invokable = QMetaObject::isInvokable(classptr,"m2");
would return false,
bool invokable = QMetaObject::isInvokable(classptr,"m1");
would return true,
bool invokable = QMetaObject::isInvokable(classptr,"nosuchmethod");
would return false. I found a method called:
int QMetaObject::indexOfMethod(const char *method) const
But it doesn't seem to care about the class, just the method name. How can that be usefull, some class A might have an "M1" defined will class B might not have an "M1" method defined.

AFAIK, there is no such function available but you can easily write your own by taking advantage of QMetaObject::indexOfMethod() (as proposed by #Igor Tandetnik).
It returns -1 if the method is not found (it returns its index otherwise).
Something like:
bool isInvokable(QObject * obj, const char * method)
{
return obj->metaObject()->indexOfMethod(method) != -1;
}

Related

Function Pointers as Event Callbacks in a st

I am currently trying to implement an event system where layers can subscribe to certain event types. I am struggling with function pointers for the callback methods. In the layer.h file I have the OnEvent function and a function pointer which looks like this:
void OnEvent(const Event& e);
void(Engine::Layer::*m_EventCallback)(const Event& e);
In the constructor of a layer I simply do this:
m_EventCallback = OnEvent;
To keep track of which layer subscribed to which EventType I have defined a struct as folling:
struct CallbackData {
EventType type;
void(Engine::Layer::*OnEvent)(const Event& e);
int layerID;
bool isActive;
};
I have an EventDispatcher and its dispatch function looks something like this:
bool EventDispatcher::Dispatch(const Event& e)
{
for (CallbackData& calldata : m_Callbacks) {
if (calldata.type == e.GetEventType() && calldata.isActive) {
calldata.OnEvent(e);
}
}
//TODO work on this so it only returns true if the event has been properly dispatched
return true;
}
There is also a subscribe function which creates an instance of CallbackData and pushes it into a vector which looks like this:
void EventDispatcher::Subscribe(EventType type, void(Engine::Layer::*OnEvent)
(const Event& e), int layerID)
{
CallbackData temp = { type, OnEvent, layerID, true };
m_CallbackInsert = m_Callbacks.emplace(m_CallbackInsert, temp);
}
So if the type is of callback data is the same as the event references type the OnEvent function should get called via the function pointer.
The function pointer defintion needs to have Engine:: which is just a namespace and Layer which is the class where the OnEvent lies. I dont know why it needs the namespace because everything I do here is defined in the namespace.
But the main question is how do I properly define the function pointer and then call it the way showcased here?
The exact error message is this:
expression preceding parentheses of apparent call must have(pointer-to-)function type
Please dont link sites with already implemented event systems. I have already looked at those and didnt really understand much. Thats why I want to do it myself so I do understand it.
Thanks in advance!
Assuming I understand what you're doing...
You have an EventDispatcher, and he needs to keep a registry of possible callbacks to make. I'm going to cut & paste a little code I use then explain it.
First, this is the relevant portion of my Route object.
class Route {
public:
typedef std::function<void(const HTTPServerRequest &, HTTPServerResponse &)> Callback;
Callback callback;
};
class Router {
public:
void addRoute(const std::string &method, const std::string &path, Route::Callback callback);
};
That part works about how you would expect and doesn't require anything special. This creates an array of Route objects, with the callback method being given the callback passed into addRoute(). When I want to dispatch on this particular route:
route->callback(request, response);
You probably know that part, too.
For my code, I'm making method calls into an object. To pass that, you have two choices. The first is to use std::bind() -- which I really dislike.
So I use lambdas.
addRoute("GET", "/ping", [=](const HTTPServerRequest &request, HTTPServerResponse &response) { ping(request, response); } );
Is this absolutely the most efficient? I have no idea. But performance isn't ultra-sucky, so this is what I do.
Basically, I keep std::function<> pointers, and those are really easy to use. You can pass a lambda as a std::function<> as long as the signature matches.
The other choice is to use std::bind -- which, as I said, I don't like, mostly because I think it's uglier than using a lambda. But that's definitely an opinion, not a fact. Using std::bind may be a better way, but I don't have any code to show you doing it that way.
I'm not entirely sure this actually solves the confusion you're having, but if it's close, just comment, and I'll try to clarify.

C++ Setting member object which has const member

I am using OIS for handling my input with Ogre and currently, on KeyPress/Release a Message object like the following will be constructed and distributed among subscribers.
class Message
{
public:
Message();
~Message();
inline void SetKeyEvent(const OIS::KeyEvent& keyEvent) { _keyEvent = keyEvent; }
const OIS::KeyEvent& GetKeyEvent() const { return _keyEvent; }
private:
OIS::KeyEvent _keyEvent;
};
Since this object will be constructed/destroyed whenever input is received via keyboard, I am trying to store a pre-constructed Message object and then simply update the _keyEvent field with the new data, before distributing.
The problem is that the OIS::KeyEvent object has a const member which is preventing me from using the assignment operator. The SetKeyEvent method gives me the following syntax error:
function "OIS::KeyEvent::operator=(const OIS::KeyEvent &)" (declared implicitly) cannot be referenced -- it is a deleted function
I was wondering what the best way to achieve this functionality would be?
Thanks in advance
EDIT: Just to clarify, I already use initializer lists when possible. My intention is to have the Message object pre-constructed and then update the _keyEvent field with the new event data from the KeyPress event which OIS fires, using the SetKeyEvent method. I would like to know if this is possible and if so, what the best way to do it would be.
The copy operator is deleted, so you must work with pointers.
class Message
{
public:
Message();
~Message();
inline void SetKeyEvent(OIS::KeyEvent* keyEvent) { _keyEvent = keyEvent; }
const OIS::KeyEvent& GetKeyEvent() const { return _keyEvent; }
private:
OIS::KeyEvent* _keyEvent;
};
And now it's better to check if the argument in the setter isn't nullptr.
inline void SetKeyEvent(OIS::KeyEvent* keyEvent)
{
assert(keyEvent != nullptr);
_keyEvent = keyEvent;
}
assert() needs #include <assert.h>
EDIT:
Sorry, forgot the getter method. You must use pointers, too.
const OIS::KeyEvent* keyEvent = &Message.GetKeyEvent();
Where Message is your class instance.
It is possible by using placement new and an explicit destructor call, things you normally should never do:
inline void SetKeyEvent(const OIS::KeyEvent& keyEvent)
{
_keyEvent.~KeyEvent();
new (&_keyEvent) OIS::KeyEvent(keyEvent);
}
This is bad ugly horrible code, use at your own risk.

NULL check for integers in qt

I have a function in an pure virtual class that is inheritted by multiple classes. This function looks something like:
virtual quint32 myClass::getIntValue() = 0
In some classes that inherrit this function a default value should be returned since they cannot implement this function (yet). However any quint32 that I pick can also be a valid return value. So for example if I pick "0" to be the default value, I can check the return value to be "0" and act accordingly (for example ignoring that value). However there will be cases when "0" will be a valid return value that makes sense.
Is there any way around this problem?
Use boost::optional. Hopefully it'll be added to the C++17 standard.
You could return a QPair or pass a bool& like:
virtual quint32 myClass::getIntValue(bool &valid) = 0;
or
virtual QPair< quint32,bool > myClass::getIntValue() = 0;
If you can use an optional type, use it.
Otherwise, since the caller of getIntValue has to do the checks anyway, it'd be useful to force it to do the checks. Have a method the caller can use to check if getIntValue is implemented. A quick inspection of such an API makes it obvious that you need to call hasGetIntValue before you use it. It self-documents not much worse than had you used an optional type.
class MyClass {
...
virtual quint32 getIntValue() const { Q_ASSERT(false); } // or abort()
virtual bool hasGetIntValue() const { return false; }
};
class Class : public MyClass {
...
quint32 getIntValue() const Q_DECL_OVERRIDE { return 42; }
bool hasGetIntValue() const Q_DECL_OVERRIDE { return true; }
}
The caller can then check and avoid the call altogether:
if (myClassInstance.hasGetIntValue()) {
auto value = getIntValue();
...
} else {
// can't call getIntValue(), do something else
}
This approach will catch callers that don't do the check at runtime.
Note that getters usually can be declared const, and reimplementations should be declared with Q_DECL_OVERRIDE to ensure that you're actually implementing existing virtual methods, not adding new ones.
An alternative approach would be to implement some lightweight optional value class if you can't use boost::optional for whatever reason.

Don't understand how this C++ method works, and want to do something similar

I'm trying to add another function to a large program I've been working on. It's a 3D game, and a lot of it was built before I got here. If I want to add something, I'll usually look for other places where something similar has been done and make my changes based off that. In this instance however the method I'm trying to learn from is very complex and I don't really know what is going on (and thus don't know what I need to change about it to make it do what I want it to do).
Here is the normal method:
class Action_GoToZone : public Action {
public:
Action_GoToZone() {}
void eval(const Dialog& dialog, State& state) const {
ZoneParser::getSingleton().load("../media/zones/" + mZoneFilename, false);
GameState::getSingleton()._changeState("GameMode");
}
static Action* Create(const Script2::Parser::List& list) {
Action_GoToZone* action = new Action_GoToZone();
if(list.size() != 1)
throw Translator::TranslateException("GoToZone Action takes exactly one parameter");
const Script2::Parser::ListElement& e1 = list.front();
if(!e1.mIsIdentifier)
throw Translator::TranslateException("GoToZone Action only takes identifiers");
action->mZoneFilename = String(e1.mIdentifier.mString);
action->mReturnFilename = ZoneParser::getSingleton().getLastFilename();
return action;
}
private:
String mZoneFilename;
String mReturnFilename;
};
All I want my method to do is to call a function within a different class. Here is what I attempted:
class Action_SetJob : public Action {
public:
Action_SetJob() {}
void eval(const Dialog& dialog, State& state) const {
GameModeState::changeJob(1); //This is the class/function I want it to call.
}
static Action* Create(const Script2::Parser::List& list) {
Action_SetJob* action = new Action_SetJob();
if(list.size() != 1)
throw Translator::TranslateException("SetJob Action takes exactly one parameter");
const Script2::Parser::ListElement& e1 = list.front();
if(!e1.mIsIdentifier)
throw Translator::TranslateException("SetJob Action only takes identifiers");
action->GameModeState::changeJob(1);
return action;
private:
int changeJob;
}
};
I don't really know what action-> is for... I tried it with taking out action->GameModeState::changeJob(1); and all content below that but that threw up errors.
This probably isn't enough information to solve the problem, but I'd be happy with any explanation about the method, if you can.
If I understand correctly what you are trying to do, then this should accomplish it:
class Action_SetJob : public Action {
public:
Action_SetJob() {}
void eval(const Dialog& dialog, State& state) const {
GameModeState::changeJob(newJob);
}
static Action* Create(const Script2::Parser::List& list) {
Action_SetJob* action = new Action_SetJob();
if(list.size() != 1)
throw Translator::TranslateException("SetJob Action takes exactly one parameter");
const Script2::Parser::ListElement& e1 = list.front();
if(!e1.mIsInteger)
throw Translator::TranslateException("SetJob Action only takes integers");
action->newJob = e1.mInteger.mInt;
return action;
}
private:
int newJob;
};
Obviously since C++ is context-sensitive (it's actually an undecidable language), I cannot know what other members your classes have so I guessed what could be likely.
You want to parse an integer that you can pass to the function you are trying to call when the action gets evaluated.
This is assuming your changeJob method is static. If it is not actually static, you will have to somehow figure out the target object; you can do that by adding an other parameter to your script function for example.
If you want more details, we need more information!
-> is a pointer reference. It looks like your objects are pointers (from the * after the object type). Is the problem with the pointer operations or with something else? From what you wrote, I'm not exactly sure what entirely to offer help with aside from your mention of action->

calling methods in cpp like #selector(someMethod:) in Objective-C

In Objective-C you can pass a method A as a parameter of other method B.
and call method A from inside method B
very easily like this:
-(void) setTarget:(id)object action:(SEL)selectorA
{
if[object respondsToSelector:selectorA]{
[object performSelector:selectorA withObject:nil afterDelay:0.0];
}
}
Is there any functionally like this in C++ ?
C++ and Objective-C are quite different in that regard.
Objective-C uses messaging to implement object method calling, which means that a method is resolved at run-time, allowing reflectivity and delegation.
C++ uses static typing, and V-tables to implement function calling in classes, meaning that functions are represented as pointers. It is not possible to dynamically determine whether a class implements a given method, because there are no method names in memory.
On the other hand, you can use RTTI to determine whether a given object belongs to a certain type.
void callFunc(generic_object * obj) {
specific_object * spec_obj = dynamic_cast<specific_object*>(obj);
if (spec_obj != NULL) {
spec_obj->method();
}
}
Edit:
As per nacho4d's demand, here is an example of dynamic invocation :
typedef void (specific_object::*ptr_to_func)();
void callFunc(generic_object * obj, ptr_to_func f) {
specific_object * spec_obj = dynamic_cast<specific_object*>(obj);
if (spec_obj != NULL) {
((*spec_obj).*f)();
}
}
Yes there is, and they are called "Function Pointers", you will get lots of results googling around,
http://www.newty.de/fpt/index.html
http://www.cprogramming.com/tutorial/function-pointers.html