How to create delegate function in QT - c++

In C# we declare delegate function of a class like this:
public delegate void MyClassDelegate(float num);
And then we can use it on other functions like this:
public int SomeFunction(float num, MyClass.MyClassDelegate del);
How do I do this or something like this on QT?

It's not related to Qt. Use std::function for that:
void caller(int value, std::function<float(int)> delegate)
{
qDebug() << delegate(value);
}
float divide(int value)
{
return float(value) / 3;
}
int main(int argc, char *argv[])
{
caller(7, divide);
return 0;
}
If you need something elaborate (such as storing a state to create a proxy function, etc.), you can also use an object with a () operator:
struct MyDelegate
{
float operator()(int value) { return float(value) / 3; }
};
float divide(int value)
{
return float(value) / 3;
}
void caller(int value, MyDelegate& delegate)
{
qDebug() << delegate(value);
}
int main(int argc, char *argv[])
{
MyDelegate delegate;
caller(7, delegate);
return 0;
}

Related

Actual function call count doesn't match EXPECT_CALL

Im new to Gmock. I try a example but it's error. I also refer a few posts on the group but it not helpul for me.
class MATH
{
public:
virtual ~MATH(){}
virtual int Tong(int a, int b)
{
return a + b;
}
};
class MockMATH : public MATH
{
public:
MOCK_METHOD2(Tong, int(int,int));
};
class TestMATH
{
MATH m ;
public:
int TestTong(int a, int b)
{
cout<<"TONG"<<endl;
if(m.Tong(a,b))
{
cout<<"Successful"<<endl;
return a+b;
}
else
{
cout<<"Failed"<<endl;
return -1;
}
}
};
TEST(MyMathTest, Tong_by_true)
{
MockMATH mM;
TestMATH math;
EXPECT_CALL(mM,Tong(_,_));
//.WillOnce(Return(9));
int retValue = math.TestTong(4,5);
std::cout<<retValue<<std::endl;
EXPECT_EQ(retValue,9);
}
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
int ret = RUN_ALL_TESTS();
return ret;
}
and this error is showed below :
The problem is method Tong() is never called on your mock object mM. It is called on object m, member of TestMath class. That cannot work, m is not a mock object, gmock knows nothing about it and cannot track methods being called on it.
The simplest solution I see is:
class MATH { public: virtual ~MATH(){} virtual int Tong(int a, int b) { return a + b; } };
class MockMATH : public MATH
{
public:
MOCK_METHOD2(Tong, int(int,int));
};
class TestMATH
{
MockMATH m ;
public:
int TestTong(int a, int b)
{
std::cout<<"TONG"<<std::endl;
if(m.Tong(a,b))
{
std::cout<<"Successful"<<std::endl;
return a+b;
}
else
{
std::cout<<"Failed"<<std::endl;
return -1;
}
}
MockMATH& getMMath() { return m; }
};
TEST(MyMathTest, Tong_by_true)
{
TestMATH math;
EXPECT_CALL(math.getMMath(),Tong(_,_))
.WillOnce(Return(9));
int retValue = math.TestTong(4,5);
std::cout<<retValue<<std::endl;
EXPECT_EQ(retValue,9);
}
which passes the test.

Value to index in Q_ENUM

QMetaEnum contains method to convert enum index to actual value:
int value(int index) const
But how to convert back to index, for example, if I want to use enum in some control where I need sequence by index?
int index(int value) const
?
Use the following function:
int indexFromValue(const QMetaEnum & e, int value){
for(int ix=0; ix< e.keyCount(); ix++){
if(e.key(ix) == e.valueToKey(value))
return ix;
}
return -1;
}
Example:
#include <QCoreApplication>
#include <QMetaEnum>
#include <QObject>
class Foo : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
enum class FooEnumType { TypeA=10, TypeB=21 };
Q_ENUM(FooEnumType)
};
static int indexFromValue(const QMetaEnum & e, int value){
for(int ix=0; ix< e.keyCount(); ix++){
if(e.key(ix) == e.valueToKey(value))
return ix;
}
return -1;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const QMetaObject &mo = Foo::staticMetaObject;
int index = mo.indexOfEnumerator("FooEnumType");
QMetaEnum metaEnum = mo.enumerator(index);
Q_ASSERT(indexFromValue(metaEnum, 10) == 0);
Q_ASSERT(indexFromValue(metaEnum, 21) == 1);
Q_ASSERT(indexFromValue(metaEnum, 100) == -1);
return 0;
}
#include "main.moc"

Using QtConcurrent::MappedReduce in a class

I am currently learning QtConncurrenct for multi threaded applications. So for testing purposes I decided to implement a simple program that sums integers in a list, here is the code:
#include <QCoreApplication>
#include <QtConcurrent>
#include <functional>
class intObj{
int m_value;
public:
intObj(int val = 0):m_value(val){}
int val() const {return m_value;}
};
static intObj mapFunction(const intObj &num){
return intObj(num.val());
}
static void reduceFunction(intObj &sum, const intObj &term){
int x = sum.val();
int y = term.val();
sum = intObj(x+y);
}
class myTest{
public:
int getSum(QList<intObj> numbers);
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<intObj> n;
for(int i = 0; i < 1000 ; i++){
n.append(intObj(i));
}
myTest m;
int sum = m.getSum(n);
return a.exec();
}
int myTest::getSum(QList<intObj> numbers){
auto sum = QtConcurrent::mappedReduced(numbers,mapFunction,reduceFunction);
return sum.result().val();
}
This program now runs correctly but the map and reduce functions are outside the class. How can I modify this program such that map and reduce functions are in class intObj?
I would really appreciate a working example. Thanks in advance.
You cannot pass pointer to method to mappedReduced like that.
If you don't need the object inside the MapFunction and ReduceFunction, you should make the two functions static:
static int mappedFunction(const int num){
return num;
}
static void reduce(int &sum, const int term){
sum += term;
}
If you need to use the object, you could use std::bind (see using bound function arguments):
auto sum = QtConcurrent::mappedReduced(numbers,
std::bind(&myTest::mappedFunction, this, std::placeholders::_1),
std::bind(&myTest::reduce, this, std::placeholders::_1, std::placeholders::_2));
// Or lambda if Qt support them:
auto sum = QtConcurrent::mappedReduced(numbers,
[this] (int num) { mappedFunction(num); },
[this] (int &sum, int num) { reduce(sum, num); });
You could also use Function Objects and store a reference to your current myTest instance.
After a little more digging and rereading the Qtconcurrency on using member functions
I realised that there are 2 major points
The class of the container and the member functions SHOULD be the same
In order to avoid head aches with passing this parameter, make the member functions static
Here is the final working version
#include <QCoreApplication>
#include <QtConcurrent>
#include <functional>
class intObj{
int m_value;
public:
intObj(int val = 0):m_value(val){}
int val() const {return m_value;}
static intObj mapFunction(const intObj &num){
return intObj(num.val());
}
static void reduceFunction(intObj &sum, const intObj &term){
int x = sum.val();
int y = term.val();
sum = intObj(x+y);
}
};
class myTest{
public:
int getSum(QList<intObj> numbers);
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<intObj> n;
for(int i = 0; i < 1000 ; i++){
n.append(intObj(i));
}
myTest m;
int sum = m.getSum(n);
return a.exec();
}
int myTest::getSum(QList<intObj> numbers){
auto sum = QtConcurrent::mappedReduced(numbers,&intObj::mapFunction,&intObj::reduceFunction);
return sum.result().val();
}
Any suggestions on how to improve this program are most welcome.

String initialization in function prototype

How can we initialize a string argument in the C++ function prototype? I want to assign a default value for a string argument in my function
int test(string& s="rom");
int test(string& s) {
return s.size();
}
int main(int argc, char *argv[]) {
cout << test() << endl;
return 0;
}
You can use this:
void func(const std::string& argument = "default") { ... }
you can also do:
void func(std::string argument = "default") { ... }
but that really depends on if you need that copy inside the function.
Like this:
void func(int a, string str="default-string")
{
cout << a << str << endl;
}
And call like this:
int main(void)
{
func(3); // use default string
func(3, "new-string"); // use new string
return 0;
}

Is this a bad hack? memcpy with virtual classes

Ok, here's some hack I came up with, but I'm having some problems using it in real world code. This is a working example of what I want to do
class VirtualParent
{
public:
virtual void printVal() = 0;
};
class Parent : public VirtualParent
{
public:
virtual void printVal()
{
cout << "Val is: " << val << endl;
}
void SetVal(foo * v) { val = v; }
protected:
foo* val;
};
class Child : public Parent
{
public:
virtual void printVal()
{
cout << "From child, Val is: ";
val->print();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Parent * p_ptr = new Child;
foo * val = new foo;
p_ptr->SetVal(val);
p_ptr->printVal();
for(int n = 0;n < 100;n++)
{
Parent * new_ptr = nullptr;
//memcpy ( &new_ptr, &p_ptr, sizeof(Parent) );
memcpy_s( &new_ptr, sizeof(p_ptr),&p_ptr, sizeof(p_ptr) );
new_ptr->printVal();
}
return 0;
}
This example works if I use memcpy, or memcpy_s. The idea is to pass a user derived class to a function, that then will create several copies, but as I don't know at compile time the derived class type, I thought of that. As I said, that works perfectly, and i copied that to my engine, where i want to use it, and I'm having some memory issues appearing from nowhere, and they seem to be releated to that hack. Using memcpy_s solves some of them.
Is this something "good" to do, or there's a better way?
Here's the "real world" code
_Lua::ScriptedEntity * newScript = EntityBase;//nullptr;
//assert(HeapValidate(GetProcessHeap(),0,nullptr));
//memcpy( &newScript, &EntityBase, sizeof(_Lua::ScriptedEntity) );
memcpy_s(&newScript, sizeof(EntityBase), &EntityBase, sizeof(EntityBase));
//assert(HeapValidate(GetProcessHeap(),0,nullptr));
string luaPath = transforms.next_sibling().next_sibling().first_attribute().as_string();
newScript->CompileFile(luaPath.c_str());
auto callback = [&](_Physics::Trigger* trigger,PxTriggerPair* pairs, PxU32 count)
{
newScript->SelectScriptFunction("TriggerCallback");
newScript->AddParam(trigger->Id);
auto data = (_Physics::RayCastingStats*)pairs->otherShape->userData;
newScript->AddParam((PxU8)pairs->flags);
newScript->AddParam(data->ID);
newScript->AddParam((int)data->Type);
newScript->AddParam((int)count);
newScript->Go(1);
return;
};
((_Physics::Trigger*)EnginePTR->iPhysics->GetPhysicObject(StartingTriggerID))->InternalCallback = callback;
and the class
//class derived from LuaScript, implements a set of common use functions for AI scripts and similar. Used in the XLL parser.
class ScriptedEntity : public LuaScript
{
protected:
static const int NumberOfFunctions = 11;
std::array<function<int(LuaVirtualMachine& vm)>,NumberOfFunctions> FunctionsArray;
int m_iMethodBase;
public:
ScriptedEntity(LuaVirtualMachine& vm) : LuaScript (vm)
{
InternalEntity = new Entity;
m_iMethodBase = RegisterFunction("GetEntityPos");
RegisterFunction("GetPlayerPos");
RegisterFunction("Move");
RegisterFunction("GetEntityLife");
RegisterFunction("IsPlayerVisible");
RegisterFunction("SetOrientationFromLookAt");
RegisterFunction("RotateAxisUp");
RegisterFunction("GetEntityOrientation");
RegisterFunction("Idle");
RegisterFunction("TeleportBehindPlayer");
RegisterFunction("ApplyGravity");
FunctionsArray[0] = [this](LuaVirtualMachine& vm){ return this->GetEntityPos(vm); };
FunctionsArray[1] = [this](LuaVirtualMachine& vm){ return this->GetPlayerPos(vm); };
FunctionsArray[2] = [this](LuaVirtualMachine& vm){ return this->Move(vm); };
FunctionsArray[3] = [this](LuaVirtualMachine& vm){ return this->GetEntityLife(vm); };
FunctionsArray[4] = [this](LuaVirtualMachine& vm){ return this->IsPlayerVisible(vm); };
FunctionsArray[5] = [this](LuaVirtualMachine& vm){ return this->SetOrientationFromLookAt(vm); };
FunctionsArray[6] = [this](LuaVirtualMachine& vm){ return this->RotateAxisUp(vm); };
FunctionsArray[7] = [this](LuaVirtualMachine& vm){ return this->GetEntityOrientation(vm); };
FunctionsArray[8] = [this](LuaVirtualMachine& vm){ return this->Idle(vm); };
FunctionsArray[9] = [this](LuaVirtualMachine& vm){ return this->TeleportBehindPlayer(vm); };
FunctionsArray[10] = [this](LuaVirtualMachine& vm){ return this->ApplyGravity(vm); };
ViewRayCount = 16;
}
virtual int ScriptCalling (LuaVirtualMachine& vm, int iFunctionNumber)
{
if(iFunctionNumber - m_iMethodBase > NumberOfFunctions)
return 0;
else
return FunctionsArray[iFunctionNumber - m_iMethodBase](vm);
// The user might want to add functions to the script, and that's done by overloading this function. That's why it's virtual
}
// Functions
// Prototypes
int GetEntityPos(LuaVirtualMachine& vm);
int GetPlayerPos(LuaVirtualMachine& vm);
int AttackPlayer(LuaVirtualMachine& vm);
int Move(LuaVirtualMachine& vm);
int GetEntityLife(LuaVirtualMachine& vm);
int GetEntityRawDamage(LuaVirtualMachine& vm);
int IsPlayerVisible(LuaVirtualMachine& vm);
int SetOrientationFromLookAt(LuaVirtualMachine& vm);
int RotateAxisUp(LuaVirtualMachine& vm);
int GetEntityOrientation(LuaVirtualMachine& vm);
int Idle(LuaVirtualMachine& vm);
int TeleportBehindPlayer(LuaVirtualMachine& vm);
int ApplyGravity(LuaVirtualMachine& vm);
int ShootPlayer(LuaVirtualMachine& vm);
// Defined
bool Update(float ElapsedTime)
{
SelectScriptFunction("Update");
AddParam(ElapsedTime);
Go(1);
SelectScriptFunction("Clear"); // dummy function to clean the stack
Go();
return InternalEntity->Alive;
}
void HandleReturns (LuaVirtualMachine& vm, const char *strFunc)
{
if(string(strFunc) == "Update")
{
// frames returns an answer of the stack
lua_State *state = (lua_State *) vm;
InternalEntity->Alive = lua_tonumber(state,-1) != 0;
}
}
// Vars
Entity * InternalEntity;
void * EnginePTR_voidptr;
int PhysicID,VisualID,PlayerID;
int ViewRayCount;
};
Also, the memcpy happends inside:
HRESULT LoadSceneSimple(string Path,
int StartingModelID,
int StartingInstanceID,
int StartingEmmitterID,
int CameraID,
int StartingTriggerID,
int StartingMaterialID,
int StartingPhysicsID,
int ShaderID,
void* engPtr,function<void(_X3D::BaseEffect* effect, _X3D::MaterialValues* matt,int ObjectID,int ShaderID)> MaterialCallback,
string subfolder,
_Lua::ScriptedEntity * EntityBase, string LuaSubfolder);
You are just copying a pointer.
Even so, you cant use memcpy the way you are trying to, since you need to know how big the associated memory is (that the pointer is pointing to), which can vary based on the concrete class.
One way to do what you intend is to add a virtual Parent* Parent::clone() function which then gets overriden by Child* Child::clone().
Then you can do something like Parent* new_parent = p_ptr->clone() without needing to know the subclass.
It is assumed that the clone() function would take care of allocating (new) the heap memory for the correct/equivalent type.