I wrote the code below, but I get a notification saying No viable overloaded "=".
(Note that the list id contains some strings)
QList<QString>id;
QList<int>::iterator iter;
iter = std::find(logid.begin(), logid.end(), id);
The issue is that you are using the std::find function incorrectly. You are also trying to find inside a list another list.
Try this:
#include <QtDebug>
QList<int> logid = {1, 2, 3};
QList<QString> ids = {"2", "5"};
for (const auto &id : ids) {
auto it = std::find_if(logid.begin(), logid.end(), [&](const int x) {
return x == id.toInt();
});
if (it != logid.end()) {
// Valid item
qDebug() << "Address" << ⁢
qDebug() << "Value" << *it;
}
}
Note: since ids is a List of QString, you need to convert it to int.
Related
I get an error when I use myRand::RandInt instead of something like default_random_engine. But I don't understand how am I supposed to implement the random_engine function. What I've done works well with std::random_shuffle, but I understand that this function was deprecated, and std::shuffle is preferred.
I am trying to get this to work:
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::shuffle (v.begin(), v.end(), myRand::RandInt);
return 0;
}
I've defined a namespace to implement the functions:
namespace myRand {
bool simulatingRandom = false;
std::vector<int> secuenciaPseudoRandom = {1,0,1,0};
long unsigned int index = 0;
int Rand() {
//check
if (index > secuenciaPseudoRandom.size() - 1 ) {
index = 0;
std::cout << "Warning: myRand resetting secuence" << std::endl;
};
if (simulatingRandom) {
//std::cout << "myRand returning " << secuenciaPseudoRandom[i] << std::endl;
return secuenciaPseudoRandom[index++];
}
else {
return rand();
}
}
// works as rand() % i in the case of simulatingRandom == false
int RandInt(int i) {
return Rand() %i;
}
}
Basically I want to be able to change between simulating random and true random easily for testing purposes. So that in my main code I can do the testing with simulatingRandom set to true and then change it to false. Maybe there is a better way to do testing of functions that involves random. If so, I am open to any suggestions.
the last argument to std::shuffle must meet the requirements of UniformRandomBitGenerator. The generator should be an object not a function. For example a minimal implementation would be:
struct RandInt
{
using result_type = int;
static constexpr result_type min()
{
return 0;
}
static constexpr result_type max()
{
return RAND_MAX;
}
result_type operator()()
{
return Rand();
}
};
You can then call it as:
std::shuffle (v.begin(), v.end(), myRand::RandInt());
Note that you'l need to adjust the values of min and max if you set your simulatingRandom value to true to match the expected values. If they don't match the true values std::shuffle probably wont be as random as it should be.
Have to finish with the usual reminder not to use rand in modern code: Why is the use of rand() considered bad? especially without calling srand first. The use of rand is the main reason std::random_shuffle is deprecated.
Lets say Typed Actor A needs to command Typed Actor B to do something. Actor A also needs to know if the command ran succesfully or not but does not want to block operation until this response arrives. My current working theory is that this is best satisfied with Requests. More specifically request(...).then
There is a nice example called "request.cpp" that I have been playing with. My challenge is that I don't really need actor B to return any data. I just need to know if the command was successful or not and if not what error was thrown.
So my question is two fold: 1) Am I correct in thinking that request(...).then is the correct mechanism to do what I want and 2) if so then can a request handle a response that has no data?
This is what I'm trying:
#include <chrono>
#include <cstdint>
#include <iostream>
#include <vector>
#include "caf/all.hpp"
using std::endl;
using std::vector;
using std::chrono::seconds;
using namespace caf;
using cell
= typed_actor<result<void>(get_atom, int32_t)>;
struct cell_state {
static constexpr inline const char* name = "cell";
cell::pointer self;
cell_state(cell::pointer ptr) : self(ptr) {}
cell_state(const cell_state&) = delete;
cell_state& operator=(const cell_state&) = delete;
cell::behavior_type make_behavior() {
return {
[=](get_atom, int32_t input) -> result<void> {
if (input != 5) { // Simulate command successful or not
return; // If successful, then return;
}
else {
return sec::unexpected_message; // If not then return error.
}
},
};
}
};
using cell_impl = cell::stateful_impl<cell_state>;
void multiplexed_testee(event_based_actor* self, vector<cell> cells) {
for (cell& x : cells) {
aout(self) << "cell #" << x.id() << " calling" << endl;
self->request(x, seconds(1), get_atom_v, static_cast<int32_t>(x.id()))
.then(
[=](void) {
aout(self) << "cell #" << x.id() << " -> " << "success" << endl;
},
[=](error& err) {
aout(self) << "cell #" << x.id() << " -> " << to_string(err) << endl;
});
}
}
void caf_main(actor_system& system) {
vector<cell> cells;
for (int32_t i = 0; i < 5; ++i)
cells.emplace_back(system.spawn<cell_impl>());
scoped_actor self{ system };
auto x2 = self->spawn(multiplexed_testee, cells);
self->wait_for(x2);
}
CAF_MAIN()
When I compile, I get an error on the empty return statement saying "return-statement with no value, in function returning caf::result<void>. Is there a better way to do this?
My backup plan is to change my command definition to just return a standard error and return sec::none if the operation was successful. But I'm afraid that approach violates the spirit of the whole optional-second-parameter for error conditions. How well am I thinking about all this?
Is there a better way to do this?
You had the right idea. The result<void> expects either an error or a 'void' value. Since void{} isn't a thing in C++, you can do return caf::unit; to tell result<void> to construct an "empty" result. On the receiver's side, you already did the right thing: then with a lambda taking no arguments.
Minor point:
[=](void) { ... }
This is a C-ism from the early days where the compiler allowed you to do silly things. Just drop the void, it serves no purpose. :)
From the Qt documentation about QMap::iterator :
Unlike QHash, which stores its items in an arbitrary order, QMap
stores its items ordered by key. Items that share the same key
(because they were inserted using QMap::insertMulti(), or due to a
unite()) will appear consecutively, from the most recently to the
least recently inserted value.
What I want is to interate a map by inserted index. For example this map.
const static QMap<QString, int> MEASUREMENT_COLUMNS{{"ID", MY_SQL_BIGINT}, {"logging_id", MY_SQL_INT}, {"calibration_id", MY_SQL_INT}, {"logging_comment", MY_SQL_VARCHAR255}, {"measurement_date_time", MY_SQL_DATETIME}, {"ADC0", MY_SQL_FLOAT},
{"ADC0", MY_SQL_FLOAT},
{"ADC1", MY_SQL_FLOAT},
{"ADC2", MY_SQL_FLOAT},
But the problem is as the documentation says above about QMap and QHashmap. They will not work for be if I want to iterate a map by inserted index.
For example, first ID, then logging_id, then calibration_id etc.
So I need to select something else than QMap and QHash.
Question:
Is there a map-like tool in QT that can be iterated over inserted index?
You can use two QVector, or use QVector<QPair<QString, int> > instead.
Here's the start of a QHash derivative which provides this functionality. DISCLAIMER: This is not entirely perfected! Not every function / feature of QHash has yet been accounted for. As long as you only use the functions / operator overloads provided here, you'll be fine for sure. If someone wants to keep developing this and repost a truly "finished" class, that would be great!
Note that performance will of course be degraded a bit, and memory consumption will increase, using this vs the natural QHash, but for small data sets that should be negligible.
OrderedHash.h
#ifndef ORDEREDHASH_H
#define ORDEREDHASH_H
#include <QHash>
#include <QVector>
#include <QDataStream>
#include <QDebug>
template<class K, class V>
class OrderedHash : public QHash<K,V>
{
public:
using QHash<K,V>::QHash;
#ifdef Q_COMPILER_INITIALIZER_LISTS
OrderedHash( std::initializer_list<std::pair<K, V>> list )
: QHash<K,V>::QHash()
{ foreach( auto p, list ) insert( std::get<0>(p), std::get<1>(p) ); }
#endif
// Returns the keys in the order they were inserted.
// If the ordered keys vector is blatantly out of sync with the hash
// (as may occur via the use of QHash functions not accounted for
// by this override!), this returns UNordered keys, since those are at
// least accurate.
QList<K> orderedKeys() const {
if( QHash<K,V>::size() != orderedKeys_.size() )
{
qWarning() << "OrderedHash keys are out of sync!";
return QHash<K,V>::keys();
}
return orderedKeys_.toList();
}
// This insert override "appends" to the "end" of the hash. If the key is
// already present, the entry is "moved" to the new end.
typename QHash<K,V>::iterator insert( const K &key, const V &value )
{
//qDebug() << "OrderedHash insert: " << key << ":" << value;
orderedKeys_.removeAll( key );
orderedKeys_.push_back( key );
return QHash<K,V>::insert( key, value );
}
// This additional update function perseveres the "key order" while
// modifying the value. If the key is not yet present, the entry is
// appended to the "end" of the hash.
typename QHash<K,V>::iterator update( const K &key, const V &value )
{
if( !QHash<K,V>::contains( key ) ) return insert( key, value );
return QHash<K,V>::insert( key, value );
}
int remove( const K &key )
{
orderedKeys_.removeAll( key );
return QHash<K,V>::remove( key );
}
void clear()
{
orderedKeys_.clear();
QHash<K,V>::clear();
}
private:
QVector<K> orderedKeys_;
};
// COPIED AND TWEAKED QT SOURCE FOR THESE STREAM OPERATOR OVERLOADS
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, OrderedHash<Key, T> &hash)
{
QDataStream::Status oldStatus = in.status();
in.resetStatus();
hash.clear();
quint32 n;
in >> n;
for (quint32 i = 0; i < n; ++i) {
if (in.status() != QDataStream::Ok)
break;
Key k;
T t;
in >> k >> t;
/* ORGINAL QT SOURCE
hash.insertMulti(k, t);
*/
//---------------------------------
hash.insert(k, t);
//---------------------------------
}
if (in.status() != QDataStream::Ok)
hash.clear();
if (oldStatus != QDataStream::Ok)
in.setStatus(oldStatus);
return in;
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const OrderedHash<Key, T>& hash)
{
out << quint32(hash.size());
/* ORGINAL QT SOURCE
typename QHash<Key, T>::ConstIterator it = hash.end();
typename QHash<Key, T>::ConstIterator begin = hash.begin();
while (it != begin) {
--it;
out << it.key() << it.value();
}
*/
//---------------------------------
const QList<Key> keys( hash.orderedKeys() );
foreach( auto key, keys ) out << key << hash.value(key);
//---------------------------------
return out;
}
#endif // ORDEREDHASH_H
Not in QT (to my knowledge, at least).
Can you use Boost, e.g. boost::multiindex? Another option is to combine map with vector in a class +- like this (this is likely to contain errors; it's supposed to illustrate the general idea, not to be a fully working piece of code):
template<typename K, typename V>
class indexed_map
{
map<K, V> m_map;
vector<K> m_insertionOrder;
public:
void insert(const K& k, const V& v)
{
m_map.insert(k,v);
m_insertionOrder.push_back(k);
}
V byKey(const K& k) const {return m_map.at(k)};
V byOrder(size_t n) const {return m_map.at(m_insertionOrder.at(n));}
};
Of course you'll have to write some boilerplate (ok, lots of it in fact), iterators might be also tricky.
As everyone knows, in JavaScript all functions can take any number of arguments.
In Qt you can make QObject, whose methods accessible from QML, having marked it by Q_INVOKABLE. For example:
class myObj: public QObject
{
Q_OBJECT
//...
public slots:
Q_INVOKABLE QJSValue myFunction(QJSValue value);
//...
};
And then you can call it from JS:
(function(){
//like this:
var result = myObj.myFunction("test");
//but also like this:
var result2 = myObj.myFunction(1,2,3,4,5); //,6,7,8, ..., 9998, 9999
})();
So, how to handle variable number of parameters on C++ side? On JS side we have "arguments" object. Is there any analog for Q_INVOKABLE methods?
It seems to be impossible to do by normal way. For now I've ended up with workaround.
QJSValue can contain any JS type. Including array. So method could seems like that:
QJSValue myObject::test(QJSValue arg1, QJSValue arg2, QJSValue rest)
{
qDebug() << "arg1 = " << arg1.toString();
qDebug() << "arg2 = " << arg2.toString();
auto args = toJSValueList(rest);
qDebug() << "args = [";
for(auto arg : args) {
qDebug() << " " << arg.toString() << ",";
}
qDebug() << "]";
return (arg1.isUndefined() ? 0 : 1) + (arg2.isUndefined() ? 0 : 1) + args.length();
}
Arguments arg1 and arg2 are required. Rest of arguments can be passed to method as third argument - an array. Method toJSValueList is just a helper that converts QJSValue, contained array to QJSValueList.
QJSValueList myObject::toJSValueList(QJSValue arg)
{
QJSValueList list;
auto length = arg.property("length");
if(length.isNumber()){
for(int i = 0, intLength = length.toInt(); i < intLength; ++i){
list << arg.property(static_cast<quint32>(i));
}
} else if(!arg.isUndefined()){
list << arg;
}
return list;
}
This is enough to make things work. But if someone actually need to pass any number of arguments direct to function (not through array), it can be done with a little hack.
class myObject: public QObject, public QmlSingletonProvider<QmlTimer>
{
Q_OBJECT
public:
//...
// declare property of type QJSValue which will actually be a function
Q_PROPERTY(QJSValue variadic_test READ variadic_test)
public slots:
Q_INVOKABLE QJSValue test(QJSValue arg1, QJSValue arg2, QJSValue rest);
private:
QJSValueList toJSValueList(QJSValue arg);
QJSValue variadic_test(); // getter for property
QJSValue variadic_test_fn; // stored JS function
};
// variadic wrapper for method test()
QJSValue myObject::variadic_test()
{
if(variadic_test_fn.isCallable())
return variadic_test_fn;
auto engine = qjsEngine(this);
if(!engine) return QJSValue();
variadic_test_fn = engine->evaluate("function(){ return this.test( arguments[0], arguments[1], Array.prototype.slice.call( arguments, 2 ) ); }");
return variadic_test_fn;
}
QJSValue can also be a function. So you can add an readonly Q_PROPERTY with type of QJSValue and assign JS function to it on first property access. This function will be a wrapper, that just gather all its arguments to array and pass it to your actual method. From JS you can see and call both functions: the actual one and the variadic wrapper. In the example I've passed first two arguments as is ("undefined" will be passed, if number of arguments is less than 2.), since method "test" waiting for at least 2 arguments. And rest of arguments gathered to an array by "Array.prototype.slice.call( arguments, 2 )". You can use "function(){ return this.test( Array.prototype.slice.call( arguments ) ); }" if you don't have required parameters.
Of course your C++ method should be ready for possible "undefined" values. And type of each argument need to be checked by hand. It's seems more like "JS code", even though it written on C++.
It's looks like this is impossible for every QObject, but you can wrap your singleton C++ backend SLOT with custom JS script, which will join together multiple arguments to single array. This can be done through the qmlRegisterSingletonType method callback, which provides access to the QJSEngine instance.
QJSValue ApiProvider::initSingletonType(QQmlEngine *qmlEngine, QJSEngine *jsEngine) {
qDebug() << "ApiProvider initSingletonType";
Q_UNUSED(qmlEngine);
QJSValue instance=jsEngine->newQObject(new ApiProvider(jsEngine));
QJSValue restProvider=jsEngine->evaluate(
"(function (instance) {" \
" instance.createElement=function(type,...child){" \
" return instance.createElementInternal(type,child);" \
" }; " \
" return instance;" \
"})"
);
if (restProvider.isError()) {
qCritical() << restProvider.toString();
return QJSValue();
} else {
QJSValue result=restProvider.call({instance});
if (result.isError()) {
qCritical() << result.toString();
return QJSValue();
} else {
return instance;
}
}
}
...
qmlRegisterSingletonType(
"com.tripolskypetr.quitejs",
1, 0,
"Api",
ApiProvider::initSingletonType
);
This sample implements a conditional jsx factory, where each element can have an arbitrary number of descendants in rest parameters. The source code is ready to production.
You can take QList<QVariant> as the argument to your C++ Q_INVOKABLE function and pass any array in qml side like ["string", 1, 2, 3]. QVariant is convertible to most of all basic data types.
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]