Using QMap and getting compile error messages - c++

I am trying to use a "QMap", in the class prototype:
QMap<QString, TargetsInfo*> m_targets;
In an access method I have:
TargetsInfo* TargetsModel::addTarget(int division, int camera, int map) const {
TargetsInfo* target = getTarget(division, camera, map);
if (target == nullptr) {
const QString key = makeKey(division, camera, map);
target = new TargetsInfo();
if ( target != nullptr ) {
m_targets.insert(key, target);
}
}
return target;
}
TargetsInfo* TargetsModel::getTarget(int division, int camera, int map) const {
const QString key = makeKey(division, camera, map);
QMap<QString, TargetsInfo*>::iterator itr = m_targets.find(key);
return (its == m_targets.end()) ? nullptr : itr.value();
}
When I compile I get the following errors which I am struggling to see what is wrong:
C2663: 'QMap<QString, TargetInfo *>::insert': 2 overloads have no legal conversion for 'this' pointer
C2440: 'initialising': cannot convert from 'QMap<QString, TargetInfo *>::const_iterator' to 'QMap::<QString, TargetInfo *>::iterator'
No constructor could take the source type, or constructor overload resolution was ambiguous

For the second error change
QMap<QString, TargetsInfo*>::iterator itr = ...
to
QMap<QString, TargetsInfo*>::const_iterator itr = ...
Your getTarget method is const so m_targets.find returns a const iterator (otherwise you could change m_targets inside your supposedly const method).
For the first error, remove const from your addTarget method. Obviously a method which adds items to m_targets should not be const.

Related

no matching function call to error in vector.push_back

I am getting the following error while compiling my C++ program:
error: no matching function for call to 'std::vector<ChainingTable<int>::Record, std::allocator<ChainingTable<int>::Record> >::push_back(ChainingTable<int>::Record*)'
324 | vector_.push_back(new Record(key, value));
The error is coming from the line:
template <class TYPE>
bool ChainingTable<TYPE>::update(const std::string &key, const TYPE &value)
{
if (!keyExists)
{
vector_.push_back(new Record(key, value));
}
}
This is defined for the class:
class ChainingTable : public Table<TYPE>
{
struct Record
{
TYPE data_;
std::string key_;
Record(const std::string &key, const TYPE &data)
{
key_ = key;
data_ = data;
}
};
std::vector<std::vector<Record>> records_;
int capacity_; // capacity of the array
Complete code:
int sz = numRecords();
bool rc = true;
std::hash<std::string> hashFunction;
size_t hash = hashFunction(key);
size_t idx = hash % capacity_;
std::vector<Record> vector_ = records_[idx];
bool keyExists = false;
for (int i = 0; i < vector_.size(); i++)
{
if (vector_[i].key_ == key)
{
vector_[i].data_ = value;
keyExists = true;
}
}
if (!keyExists)
{
vector_.push_back(new Record(key, value));
}
What could be the reason for this?
Your vector is declared to store objects of type Record, not pointers to them (Record *) but you are trying to push result of operator new which returns Record *, just use std::vector::emplace_back instead:
vector_.emplace_back(key, value);
Note: in this line
std::vector<Record> vector_ = records_[idx];
you create a copy and later modify it, seems that you need a reference.
Note2: in your search loop you do not terminate even if you find object already, you should add break into if statement, that will make it more effective.
The problem is that your variable vector_ holds objects of type Record but when you write:
vector_.push_back(new Record(key, value));
You are trying to add a pointer to a Record object in the vector vector_ instead of adding the Record object itself.
You can solve it by writing:
vector_.emplace_back(key, value);
Alternate solution
Note that there is another possible solution which is to use:
vector_.push_back(Record(key, value));
But using emplace_back should be preferred.

C++ calling a function pointer stored in a struct in a map

I am getting the error term does not evaluate to a function taking 1 arguments when trying to call a function pointer.
The function pointer is stored in a struct. The struct is then stored in a map.
Definition:
typedef void (CLIOptions::*OptionHandler)(QString);
struct OptionDefinition {
QString name;
QString description;
QString type;
OptionHandler handler;
};
typedef std::map<QString, OptionDefinition> CLIOptionMap;
I initialise the map like this:
CLIOptionMap optionMap =
{
{
QString("set-tcp-host"),
{
QString("set-tcph"),
QString("Set the TCP server host address"),
QString("string"),
&CLIOptions::setTcpHost
}
},
// etc...
}
The problem occurs when I try to iterate through the map and call the handler:
for (it = optionMap.begin(); it != optionMap.end(); ++it) {
QString value = /*snip...*/
(it->second.handler)(value)
}
What is my problem here?
Your problem is that you don't have a function pointer, you have a pointer to member function, and they are very different beasts. A pointer-to-member-function isn't even a pointer in general (it has to be able to handle pointer to a virtual function in a second virtual base class!)
Given you have a pmf, you need an object to invoke the pmf on. So something like:
for (it = optionMap.begin(); it != optionMap.end(); ++it) {
QString value = /*snip...*/
const auto pmf = it->second.handler;
(mOptionHandler.*pmf)(value);
}
actually, if you going to use C++11 auto, you can also use the foreach loop:
for (const auto& option : optionMap) {
const auto pmf = option.handler;
(mOptionHandler.*pmf)(option.value);
}

Find and update a custom object inside a std::set on C++

I have created 2 custom structs on my project and each one have a std::set.
struct Subject {
std::string name;
std::set<SubjectFrame> frames;
Subject(std::string subject_name);
void AddFrame(SubjectFrame &frame);
bool operator<(const Subject &rhs) const { return (name < rhs.name);}
bool operator==(const Subject &rhs) const { return (name == rhs.name);}
};
struct Dataset {
std::set<Subject> subjects;
std::map<int, std::vector<Subject> > classification_groups;
Dataset(const std::string ds_path);
void AddSubject(Subject &subject);
void GetDSFromFileSystem(const std::string dataset_path);
void GetClassificationGroups(int number_of_groups_to_create);
};
Every time I wanna add some frame to my set 'frames' I call this function:
void Dataset::AddSubject(Subject &subject) {
set<Subject>::iterator it = this->subjects.find(subject);
if (it != this->subjects.end()) {
for (Subject fr : this->subjects) {
it->AddFrame(fr);
}
} else this->subjects.insert(subject);
}
That calls this function:
void Subject::AddFrame(SubjectFrame &frame) {
set<SubjectFrame>::iterator it = this->frames.find(frame);
if (it != this->frames.end()) {
if (frame.l_eye_centroid.x != 0) {
it->r_eye_centroid = frame.r_eye_centroid;
it->l_eye_centroid = frame.l_eye_centroid;
}
if (frame.path != "") it->path = frame.path;
else return;
}
else this->frames.insert(frame);
}
So, the logic behind an add operation is: I pass an object and check if there's a object with that name already inside my std::set. If yes, I update the existent object with the informations that my parameter object has and the already registered object don't have, if no I insert the object.
I'm getting this errors when I try to compile my program:
error: no viable overloaded '='
it->r_eye_centroid = frame.r_eye_centroid;
error: no viable overloaded '='
it->l_eye_centroid = frame.l_eye_centroid;
error: no viable overloaded '='
if (frame.path != "") it->path = frame.path;
error: member function 'AddFrame' not viable: 'this' argument has type
'const Subject', but function is not marked const
it->AddFrame(fr);
Someone has any idea what is causing, and how I can solve, these problems?
For std::set, iterator-s are const, this is because they are used as key in the set which should not be modified to avoid any inconsistencies in strict weak ordering.
One way so solve it is to make the field you want to modify mutable, but make sure it is not used in your set ordering.

Intel tbb::parallel_for_each compile time error

I was parallelizing a for loop (that iterates through a stl list) using parallel_for_each, but I got a compile time error saying that there's no matching function call.
//TBB headers
#include "tbb/parallel_for_each.h"
class FUNCTOR
{
public:
FUNCTOR(
CLASS_A& tree,
CLASS_B *groups,
const CLASS_C** default_dominator,
const CLASS_D& filter
):
tree(tree),
groups(groups),
default_dominator(default_dominator),
filter(filter)
{}
// Iterator dereferences to a pointer
void operator()(const ELEMENT_OF_LIST_A*& keeper) const
{
/*something*/
}
private:
CLASS_A& tree;
CLASS_B *groups;
const CLASS_C** default_dominator;
const CLASS_D& filter;
};
void some_function
(
CLASS_A& tree,
CLASS_B *groups,
const CLASS_C** default_dominator,
const LIST_A& keepers,
const CLASS_D& filter
)
{
// Some code that claims processors
//LIST_A_ITER begin = keepers.begin();
//LIST_A_ITER end = keepers.end();
//const ELEMENT_OF_LIST_A* keeper = *begin
tbb::parallel_for_each
(
keepers.begin(), keepers.end(),
FUNCTOR(
tree,
groups,
default_dominator,
filter
)
);
}
Error I got was:
error: no matching function for call to 'tbb::internal::parallel_do_operator_selector<tbb::internal::parallel_for_each_body<FUNCTOR, LIST_A_ITER>, ELEMENT_OF_LIST_A*>::call(const tbb::internal::parallel_for_each_body<FUNCTOR, LIST_A_ITER>&, ELEMENT_OF_LIST_A*, tbb::internal::do_iteration_task_iter<LIST_A_ITER, tbb::internal::parallel_for_each_body<FUNCTOR, LIST_A_ITER>, ELEMENT_OF_LIST_A*>::feeder_type&)'
note: candidate is: static void tbb::internal::parallel_do_operator_selector<Body, Item>::call(const Body&, A1&, A2&) [with A1 = ELEMENT_OF_LIST_A*, A2 = tbb::internal::parallel_do_feeder_impl<tbb::internal::parallel_for_each_body<FUNCTOR, LIST_A_ITER>, ELEMENT_OF_LIST_A*>, Body = tbb::internal::parallel_for_each_body<FUNCTOR, LIST_A_ITER>, Item = ELEMENT_OF_LIST_A*]
What went wrong?
Thanks!
The operator() for FUNCTOR has an extraneous extra level of indirection. Declare it without the *, e.g.:
const ELEMENT_OF_LIST_A& keeper

QSortFilterProxyModel filterAcceptsColumn cant set new index data

im using QSortFilterProxyModel to filter column that im getting from QSqlQueryModel model
but becose the filterAcceptsColumn method is const "all the way"
i have problem to set Qt::UserRole data in the right index . how can i overcome this?
bool MiniSortFilterProxyModel::filterAcceptsColumn(int source_column, const QModelIndex& index) const
{
QVariant tmp ;
if(source_column ==0)
{
setRowid(index.data(Qt::DisplayRole));
// here im getting compilation error
//: error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const QString' (or there is no acceptable conversion)
m_rowId = index.model()->data(index,Qt::DisplayRole).toString();
return false;
}
else if(source_column ==1)
{
setYTid(index.data(Qt::DisplayRole));
return false;
}
else if(source_column ==2)
{
setNewData(index);
return QSortFilterProxyModel::filterAcceptsColumn(source_column,index);
}
return false;
}
void MiniSortFilterProxyModel::setRowid(QVariant rowId) const
{
// here also compilation error:
m_rowId = rowId.toString();
}
void MiniSortFilterProxyModel::setYTid(QVariant ytId) const
{
/ here also compilation error:
m_ytId = ytId.toString();
}
void MiniSortFilterProxyModel::setNewData(QModelIndex& index) const
{
// here also compilation error:
//error C2511: 'void MiniSortFilterProxyModel::setNewData(QModelIndex &) const' : //overloaded member function not found in 'MiniSortFilterProxyModel'
QVariant data = m_rowId+"_"+m_ytId;
index.model()->setData(index,data,Qt::UserRole);
}
Quick and dirty fix: declare m_rowId as mutable
mutable QString m_rowId;
Anyway, there's a reason if the method was declared const in the Qt API so be sure that one is the only place where you can assign that value.