PDA

View Full Version : QGenericMatrix with custom Template Type



Qtonimo
8th August 2012, 12:12
Hi,
I want to know if it is possible to create a QGenericMatrix of my own Object Type.

Like this:


QGenericMatrix<5,5,MyClass> matrix;


thanks in advance

amleto
8th August 2012, 12:35
isn't that the whole meaning of 'generic'?

Isn't it faster to try than to ask here?

Qtonimo
8th August 2012, 12:48
I tried it but the compiler doesn't like it....


class MyClass
{
private:
QString value;

public:
MyClass();
MyClass(QString value);

inline QString getValue() const { return value; }

bool operator== ( const MyClass & other ) const;
};



#include "myclass.h"

MyClass::MyClass()
{

}

MyClass::MyClass(QString value) :
value(value)
{
}

bool MyClass::operator ==(const MyClass & other) const
{
return (value == other.getValue());
}




int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QGenericMatrix<4,4,MyClass>m;
return a.exec();
}

spirit
8th August 2012, 13:04
You should implement assignment operator for your class.

amleto
8th August 2012, 14:05
I would imagine assignment is implicit.

More likely there are problems with +, *, / etc.

If op would show the compiler error then we would know for sure...

spirit
8th August 2012, 14:09
Nope, the problem is in QGenericMatrix::setToIdentity uses assignment operator which looks like ... operator = (qreal other).
But I agree with you that other common operators have to be reloaded too.

amleto
8th August 2012, 14:24
he just needs another ctor then for that issue. The assignment will be implicit



class MyClass
{
private:
QString value;

public:
MyClass();
MyClass(float f); // <<<<<<<
MyClass(QString value);

inline QString getValue() const { return value; }

bool operator== ( const MyClass & other ) const;
};

spirit
8th August 2012, 14:39
Well, yes it's another way to solve the issue, but in this case a new temporary object will be created. In the case of using assignment operation that will not happen.
Implicit anything it's evil. :)

Qtonimo
8th August 2012, 14:42
I tried it with MyClass(float f) and it works...thanks

@spirit maybe you can show me the assignment operator in this example....

is this correct?


MyClass & MyClass::operator= ( const MyClass & other )
{
this->value = other.getValue();
return *this;
}

yeye_olive
8th August 2012, 17:19
I tried it with MyClass(float f) and it works...thanks

@spirit maybe you can show me the assignment operator in this example....

is this correct?


MyClass & MyClass::operator= ( const MyClass & other )
{
this->value = other.getValue();
return *this;
}

This code is correct but not very useful: it is probably equivalent to what the compiler generates automatically.

What spirit and amleto pointed out is this:
MyClass needs a way to be assigned a qreal. One way to do that is to add a constructor MyClass(qreal), which you did. However this may be suboptimal, as assigning a qreal to a MyClass first instanciates a temporary MyClass with MyClass(qreal), then assigns it with operator(const MyClass &), then destroys the temporary. You could add an assignment operator operator=(qreal) to avoid this unnecessary construction and destruction. However since MyClass is essentially a wrapper around QString which itself uses implicit sharing, I am not convinced it will make a huge difference.

Also, it is possible that some other operators (such as binary arithmetic one) are missing from MyClass which are needed for QGenericMatrix to function properly. Errors will probably show up as soon as you try arithmetic operations on your matrices.

amleto
8th August 2012, 19:30
Well, yes it's another way to solve the issue, but in this case a new temporary object will be created. In the case of using assignment operation that will not happen.
Implicit anything it's evil. :)

only in debug build and/or poor compiler implementations, and definitely not in c++11 with move semantics :)

spirit
8th August 2012, 21:05
Here we go:


...
MyClass &operator=(qreal other)
{
value = QString("%1").arg(other);
return *this;
}
...

yeye_olive
8th August 2012, 22:14
only in debug build and/or poor compiler implementations, and definitely not in c++11 with move semantics :)
Good point.


Here we go:


...
MyClass &operator=(qreal other)
{
value = QString("%1").arg(other);
return *this;
}
...

An alternative solution would be value.setNum(other).

spirit
8th August 2012, 23:08
only in debug build and/or poor compiler implementations, and definitely not in c++11 with move semantics :)
686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00) -- still shows this. ;)

amleto
9th August 2012, 00:34
hmmm, ok, I may have 'jumped the gun' with that comment, suggesting rvo when it does not apply.

Qtonimo
9th August 2012, 09:09
Thank you guys ;)

You brought light into the darkness. :D

Qtonimo
9th August 2012, 13:19
What I have to change, if I want to store pointers in my QGenericMatrix?



QGenericMatrix<4,4,MyClass*> m;


The compiler cannot convert float to a pointer in assignment at setToIdentity()... The message is clear, but I'm not able to work arround this.

spirit
9th August 2012, 13:41
Well, it's gonna be challenging...
So, I think, you have chosen wrong type of container -- What are you using it for?

amleto
9th August 2012, 13:43
That wont work. You will need to create a wrapper.

If you want QGenericMatrix<4,4,T>, then it must support

T t;
t = 1.0f

since T is MyClass*, there is no opportunity to overload operators.

Therefore you are left with using a thin wrapper or keeping with value semantics.


template<class T>
class Wrapper
{
public:
Wrapper(T* ptr) : ptr_(ptr) {}

Wrapper& operator=(float f)
{
(*ptr) = f; // operator= (or suitable ctor) must be supported by T!
}

private:
T* ptr_;
};

Qtonimo
9th August 2012, 14:03
Pointers where my intention, because I receive lots of pointers (MyClass* pointer1, MyClass* pointer2, etc.) and want to insert them in the matrix.
If I could store pointers I would save insertion time (matrix(0,0) = pointer1...).

So I have to create every incoming myclass object on the stack and delete the pointer object on the heap : (

spirit
9th August 2012, 14:05
Use nested lists or vectors instead.
Or
Do you need matrix operations such as multiplying, subtraction etc?

Qtonimo
9th August 2012, 14:08
I need addition. This is why I use QGenericMatrix....

Pointers where my intention, because I receive lots of pointers (MyClass* pointer1, MyClass* pointer2, etc.) and want to insert them in the matrix.
If I could store pointers I would save insertion time (matrix(0,0) = pointer1...).

So I have to create every incoming myclass object on the stack and delete the pointer object on the heap : (

spirit
9th August 2012, 14:09
Ah, okay. :)

Qtonimo
9th August 2012, 14:11
So I have to create every incoming myclass object on the stack and delete the pointer object on the heap : (

The conversion from stack to heap robs performance?

amleto
9th August 2012, 14:28
Pointers where my intention, because I receive lots of pointers (MyClass* pointer1, MyClass* pointer2, etc.) and want to insert them in the matrix.
If I could store pointers I would save insertion time (matrix(0,0) = pointer1...).

So I have to create every incoming myclass object on the stack and delete the pointer object on the heap : (

with my wrapper suggestion, no you don't.