Equality operator for QFlags with scoped enum - qt

I have some flags defined as follows, using a scoped enum:
enum class Capability : int
{
NoCapabilities = 0,
SomethingCool = 1,
UberCool = 1 << 1,
EvenCooler = 1 << 2,
};
Q_DECLARE_FLAGS( Capabilities, Capability )
Now, I am trying to use the equality operator:
Capabilities(DataCapability::NoCapabilities) == Capability::NoCapabilities
I cannot use testFlag in the current example, since NoCapabilities = 0. This works if the enum is not scoped (removing class keyword).
Apparently, casting to int (static_cast<int>(NoCapabilities)) works, but it's really ugly.
What is the approach to solve this?
Is it a bad practice to have a 0 zero value and test it?

You can overload equality operator for your combination of data types. However cast ist still necessary but hidden by operator.
#include <QCoreApplication>
#include <QFlags>
#include <iostream>
enum class Capability : int
{
NoCapabilities = 0,
SomethingCool = 1,
UberCool = (1 << 1),
EvenCooler = (1 << 2),
};
Q_DECLARE_FLAGS(Capabilities, Capability)
template <typename T>
bool operator==(const QFlags<T> lhs, const Capability rhs)
{
return (QFlags<T>::Int(lhs) == static_cast<int>(rhs));
}
int main(int argc, char *argv[])
{
Q_UNUSED(argc);
Q_UNUSED(argv);
if (Capabilities(Capability::NoCapabilities) == Capability::NoCapabilities)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
if (Capabilities(Capability::EvenCooler) == Capability::NoCapabilities)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
return 0;
}

Related

Converting std::vector from BYTE to int

Code:
using ColumnIndexVector = std::vector<int>;
using ByteVector = std::vector<BYTE>;
void CCreateReportDlg::GetColumnIndexesToExclude()
{
const CString strSection = theApp.GetActiveScheduleSection(_T("Options"));
ByteVector vData = theApp.GetProfileVector(strSection, _T("AssignStatesEx"));
ColumnIndexVector vTemp(vData.begin(), vData.end()); // This converts BYTE to int
m_vColumnIndexesToExclude = vTemp;
}
Is there any way to avoid the requirement for vTemp without manually iterating vData and casting from BYTE to int?
Yes, just use assign(). IDK if you need to use clear() as well, but probably not. Just step through the runtime code the first time to know.
m_vColumnIndexesToExclude.assign(vData.begin(), vData.end());
Here's a test program:
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
using ColumnIndexVector = std::vector<int>;
using ByteVector = std::vector<BYTE>;
int main(int argc, char* argv[])
{
cout << "Test" << endl;
ByteVector bytes = {'A', 'B', 'C', 'D'};
ColumnIndexVector colVector;
for ( auto _val: bytes)
{
cout << _val << endl;
}
colVector.assign(bytes.begin(), bytes.end());
for ( auto _val : colVector)
{
cout << _val << endl;
}
return 0;
}

When does `QKeySequence::match()` return `QKeySequence::PartialMatch`?

What sequences partially match?
I thought 1 partially matches Ctrl+1, but it doesn't.
Taken from the source code,
QKeySequence::SequenceMatch QKeySequence::matches(const QKeySequence &seq) const {
uint userN = count(),
seqN = seq.count();
if (userN > seqN)
return NoMatch;
// If equal in length, we have a potential ExactMatch sequence,
// else we already know it can only be partial.
SequenceMatch match = (userN == seqN ? ExactMatch : PartialMatch);
for (uint i = 0; i < userN; ++i) {
QKeyCombination userKey = (*this)[i],
sequenceKey = seq[i];
if (userKey != sequenceKey)
return NoMatch;
}
return match;
}
It seems that,
The compared sequence has to be longer than the source
The compared sequence has to start with the source
So if you have,
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QKeySequence>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QKeySequence ks_1{Qt::CTRL, Qt::Key_X, Qt::Key_Y};
QKeySequence ks_2{Qt::CTRL};
QKeySequence ks_3{Qt::CTRL, Qt::Key_X};
QKeySequence ks_4{Qt::CTRL, Qt::Key_X, Qt::Key_Y};
QKeySequence ks_5{Qt::CTRL, Qt::Key_X, Qt::Key_Y, Qt::Key_Z};
qDebug() << ks_1.count() << ks_2.count() << ks_1.matches(ks_2);
qDebug() << ks_1.count() << ks_3.count() << ks_1.matches(ks_3);
qDebug() << ks_1.count() << ks_4.count() << ks_1.matches(ks_4);
qDebug() << ks_1.count() << ks_5.count() << ks_1.matches(ks_5);
return a.exec();
}
ks_4 would be an exact match, and ks_5 would be a partial match.
Note that the length is acquired using count(), which from the source is:
int QKeySequence::count() const
{
return int(std::distance(d->key, std::find(d->key, d->key + QKeySequencePrivate::MaxKeyCount, 0)));
}
So if the previous example is declared as:
QKeySequence ks_1{Qt::CTRL + Qt::Key_X + Qt::Key_Y};
QKeySequence ks_2{Qt::CTRL};
QKeySequence ks_3{Qt::CTRL + Qt::Key_X};
QKeySequence ks_4{Qt::CTRL + Qt::Key_X + Qt::Key_Y};
QKeySequence ks_5{Qt::CTRL + Qt::Key_X + Qt::Key_Y + Qt::Key_Z};
All will be no match, since count() returns 1 for all cases above.

How can i get data from std::map type struct?

First of all thanks a lot for helping me and reading this post.
I have this structure: x, y.
And I have a map where the data are that structure.
I would like to get data for example from iterator [1] get .x .
How can I do that?
Thanks a lot.
If you have an iterator it pointing to an element of a std::map<X, Y> then you can get a const reference to the key using it->first and a reference to the mapped type using it->second, because it points to a std::map<X, Y>::value_type value which is of type
std::pair<std::map<X, Y>::key_type const,
std::map<X, Y>::mapped_type>
For example:
Y * setX(std::map<X, X> & dict, X const & value) {
std::map<X, Y>::iterator it = dict.find(value);
if (it != dict.end())
return nullptr;
assert(it->first == value);
return &it->second;
}
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main()
{
// for a simple struct you could use "pair" (especially if you don't want to name it).
// anyway:
map<int, pair<double, string>> mymap;
mymap[0] = pair<double, string>(4.56, "hello");
mymap[1] = pair<double, string>(9.87, "hi");
for(auto & item : mymap)
{
cout << "Key: " << item.first << ", Value: [" << item.second.first << ", " << item.second.second << "]" << endl;
}
return 0;
}
Output:
Key: 0, Value: [4.56, hello]
Key: 1, Value: [9.87, hi]

Qt Q_ENUM property from QVariant(qulonglong).

Consider the following Qt code:
class Foo : public QObject {
Q_OBJECT
Q_ENUMS(E)
Q_PROPERTY(E x READ x WRITE set_x)
public:
enum E {
a = 0,
b = 1,
c = 2
};
E x() const { return x_; }
void set_x(E value) { x_ = value; }
private:
E x_;
};
int main (int argc, char **argv) {
QCoreApplication app(argc, argv);
Foo f;
f.setProperty("x", Foo::c);
std::cout << f.property("x").toInt() << std::endl; // 2
f.setProperty("x", QVariant((int)1));
std::cout << f.property("x").toInt() << std::endl; // 1
f.setProperty("x", QVariant((long long)0));
std::cout << f.property("x").toInt() << std::endl; // should be 0. is 1.
}
Why does it work that way?
If you test the return value of setProperty, you will see that the set is failing:
ok = f.setProperty("x", QVariant((long long)0));
std::cout << ok << std::endl; // 0, i.e. false
The relevant part of the Qt code is in qmetaobject.cpp, annotated below:
if (isEnumType()) {
if (v.type() == QVariant::String) {
// ... we won't get here.
} else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
// We got here because we didn't provide an int or uint.
// This will be 0...
int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
// ... which means this will return false; the property will not be set.
if ((enumMetaTypeId == 0) ||
(v.userType() != enumMetaTypeId) ||
!v.constData())
return false;
// ... we never get here
}
}
// ... we never get here
So the behavior seems to be by design: enum properties can only be set using QVariant objects with a type of int or uint.

Pass struct to function through pthread

How do I pass a struct through the pthread_create to my function? The errors I keep getting are that lower and upper has not been defined which would lead me to believe that the struct was not passed properly. I have tried referencing lower as arg1.lower and my error back is saying im trying to request for the member of a non class type void*
void * mergeSortThread(void *arg1){
std::ostringstream ostr;
ostr << "begin: " << lower << " " << upper << endl;
string message = ostr.str();
write(2, message.data(), message.length());
}
int main(int argc, char** argv)
{
struct MergeSortThreadArg
{
int * array;
int * temp;
int lower, upper;
};
pthread_attr_t attr;
pthread_attr_init(&attr);
int arr[20];
int temp[20];
MergeSortThreadArg arg;
arg.array = arr;
arg.temp = temp;
arg.lower = 0;
arg.upper = 19;
pthread_create(th, &attr, mergeSortThread, &arg);
pthread_join(th[z], NULL);
return 0;
}
Define struct before mergeSortThread() and add casting of arg1 to struct MergeSortThreadArg * it in mergeSortThread():
void * mergeSortThread(void *arg1){
struct MergeSortThreadArg *p_MST = (struct MergeSortThreadArg *)arg1;
std::ostringstream ostr;
ostr << "begin: " << p_MST->lower << " " << p_MST->upper << endl;
...
Moreover, it's more correct/safe to allocate the struct and its fields (array and tmp) to avoid passing to new thread data located on stack of another thread.

Resources