How to use QSet as value in QMap? - qt

I'm using Qt and I want to declare following container:
QMap<QUrl , QSet<ClassSharedPtr> > map;
Here ClassSharedPtr is the boost shared ptr of class "Class".
typedef boost::shared_ptr<const Class> ClassPtr;
I'm getting following errors after adding header file #include :
error: no matching function for call to ‘qHash(const boost::shared_ptr<const Class>&)’

QSet's value data type must be an assignable data type. In addition, the type must provide operator==(), and there must also be a qHash() function in the type's namespace that returns a hash value for an argument of the values's type.
So, you should implement qHash() function for boost::shared_ptr<const Class>.
namespace boost {
uint qHash(const boost::shared_ptr<const Class> &key, uint seed = 0)
{
const Class *ptr = key.get();
return uint(ptr) ^ seed;
}
}

Related

How to you use operator Int() of QFlags?

Documentation: http://doc.qt.io/qt-5/qflags.html#operator-Int
The question. I want to know what flags are set withouth testing one by one so I want the int number. Can anyone provide an example of how to use that operator in one of the many qt methods that rerturn a QFlags?
By referring to QFlags.h source code (https://android.googlesource.com/platform/prebuilts/android-emulator-build/qt/+/master/common/include/QtCore/qflags.h)
This is the definition in QFlags for "Int" operator.
Q_DECL_CONSTEXPR inline operator Int() const Q_DECL_NOTHROW { return i; }
And the "i" in return statement is declared as
Int i;
And the "Int" is declared as
typedef int Int
Notice the below two constructors of QFlags. The first constructor takes Enum as parameter and the second constructor takes QFlag as parameter.
Q_DECL_CONSTEXPR inline QFlags(Enum f) Q_DECL_NOTHROW : i(Int(f)) {}
Q_DECL_CONSTEXPR inline QFlags(QFlag f) Q_DECL_NOTHROW : i(f) {}
After noticing the above constructors, if Enum is passed to the constructor, the Enum can be a signed one or unsigned one. QFlags internally type casts it to int using Int.
Consider below example now.
//Qt::CursorShape is an Enum
Qt::CursorShape shape = Qt::ArrowCursor;
//Create QFlags object by passing "ENUM" as parameter
QFlags<Qt::CursorShape> qF(shape);
//Create QFlags object by just passing FLAG as a parameter
QFlags<Qt::CursorShape> q(Qt::ArrowCursor);
Now the situation where "Int" operator is called: In the below piece of code the first statement invokes Int operator and not in the second statement.
//Now try getting the values.
int test = qF; //In this case the "Int" operator is called.
int test1 = q;

shared_ptr not changing object (Visual studio 2012)

I have a really strange problem. I can't modify the object I am pointing to with a shared_ptr.
Example code:
#include<memory>
#include<iostream>
using namespace std;
class foo
{
public:
int asd;
foo(){}
~foo(){}
};
void d(shared_ptr<foo> c)
{
c->asd = 3;
}
void main()
{
foo a;
a.asd = 5;
d(make_shared<foo>(a));
cout<<a.asd; //asd is still 5
}
As far as I know you can access the object pointed to by the shared_ptr by using the "->" operator, so what am I doing wrong here? How can I change the asd variable inside the class via the shared pointer?
// create a temporary object by copying a
// the shared pointer you pass to d function actually points to this temporary object
d(make_shared<foo>(a));
// allocate and store foo object in shared_ptr instead
auto p_a(make_shared<foo>());
p_a->asd = 3;
d(p_a);
... so what am I doing wrong here?
From cppreference on std::make_shared [emphasis mine]:
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
Constructs an object of type T and wraps it in a std::shared_ptr
using args as the parameter list for the constructor of T.
In your case, you supply an instance of foo as argument to std::make_shared, which will be used when constructing a new object of type foo; i.e., making use of the default supplied copy CTOR of foo (foo(const foo&)). This new object will be a temporary and only live for the call to d(...).

how to append element to a QList in a structure?

I have a struct like this one :
struct Nom {
QString Nom;
....
QList<quint64> indNum;
}
In my .h file. I declare :
QVector *n;
In my .cpp file. I declare :
n = new QVector<Nom>;
I read a file to fill in n.
When I write this :
n->back().indNum.append(i->size()-1);
it works.
When I write that :
n->at(j).indNum.append(i->size()-1);
I have a compilation error:
no matching member funtion for call to 'append'
candidate function not viable: 'this' argument has type 'const
QList', but method is not marked
const void append(const T &t);
I don't understand why it works in the first case and the second.
Could anyone explain and help me solve this ?
Thanks in advance.
QVector::at returns a const reference to the Nom value, so you cannot modify the item returned by n->at(j). To get a non-const reference you can use (*n)[j].
n->back() works because for QVector::back there is a const and a non-const overload.

fill nested std::map with insert operator

I have the following code:
#include <iostream>
#include <utility>
#include <map>
using namespace std;
int main()
{
map<int, map<string, int> > mapa;
// way A
mapa[10]["aaa"] = 20;
// way B -> Compilation Error
pair<int, pair<string, int> > par(10, make_pair("aaa", 20));
mapa.insert(par);
return 0;
}
I know that "way A" of populating the map works.
I want to use "way B" but it throw a compilation Error:
error: no matching function for call to ‘std::map, int>::map(const std::pair, int>&)’
How can I populate the nested map with insert operator.
Pd: I don't use [] operator because it requires the default constructor to be defined which I don't have since I am using time_period objects from Boost.
Well the type of your map is map of (int -> map of (string -> int)) but you are trying to insert an entry of type map of (int -> pair (string, int)). A pair is not a map, thus the error.
EDIT:
According to the documentation, a call to map's [] operator is equivalent to a series of other operations:
mapped_type& operator[] (const key_type& k);
A call to this function is equivalent to:
(*((this->insert(make_pair(k,mapped_type()))).first)).second
so in your case, the call mapa[10]["aaa"] = 20; is equivalent to:
(*(( (*((mapa.insert(make_pair(10,map<string, int>()))).first)).second
.insert(make_pair("aaa",20))).first)).second
but I believe if either key 10 or aaa exist, no element will be inserted in the map. I suggest you read the docs thoroughly and test for the expected behavior.

Error: forming pointer to reference type 'const std::pair<double, unsigned int>&'.... I can't understand this error

I'm getting some errors when trying to use -> in an iterator type. When I dig in the library defining the iterator, it seems to me that everyhing is allright and that there is no reason for the error. Here is the code, part of boost::multi_array:
template <class T>
struct operator_arrow_proxy
{
operator_arrow_proxy(T const& px) : value_(px) {}
T* operator->() const { return &value_; }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
operator T*() const { return &value_; }
mutable T value_;
};
which is instantiated with const std::pair<double, unsigned int>&; then the compiler complains about "forming pointer to reference type 'const std::pair<double, unsigned int>&'".Those are internal, library substantiations. For the record, here is what I have in my code:
typedef uint32_t object_indentifier_t;
typedef std::pair< double, object_identifier_t > object_tab_t;
typedef boost::multi_array< object_tab_t, 2 > index_t;
and here is the usage that provokes the trouble:
object_identifier const& center; // Actually a parameter
index_t::const_subarray<1>::type::const_iterator pos_iterator_left = std::lower_bound( ix[i].begin(), ix[i].end(), sk[i], comparer );
assert( pos_iterator_left -> second == center ); // <-- Error steams from here
Here's more error context:
/opt/boost_1_48_0/include/boost/multi_array/iterator.hpp: In instantiation of 'struct boost::detail::multi_array::operator_arrow_proxy<const std::pair<double, unsigned int>&>':
csrc/lsh_cpp/lsh.cpp|125 col 13| required from here
/opt/boost_1_48_0/include/boost/multi_array/iterator.hpp|40 col 10| error: forming pointer to reference type 'const std::pair<double, unsigned int>&'
/opt/boost_1_48_0/include/boost/multi_array/iterator.hpp|43 col 7| error: forming pointer to reference type 'const std::pair<double, unsigned int>&'
csrc/lsh_cpp/lsh.cpp: In member function 'lsh_cpp::neighbour_iterator_t lsh_cpp::lsh_t::pimpl_t::query(const object_identifier_t&) const':
csrc/lsh_cpp/lsh.cpp|125 col 13| error: result of 'operator->()' yields non-pointer result
NOTE: This class is part of boost::multi_array, (I already wrote that), and I'm not instantiating it directly. I wrote above my instantiation. The class is instantiated by boost::multi_array this way:
operator_arrow_proxy<reference>
operator->() const
{
return operator_arrow_proxy<reference>(this->dereference());
}
The use of "reference" makes me think that the reference is intended. Is there a reason for taking address to a reference to not work? I think to remember having done it myself a couple of times, and getting the address of the original, aliased variable that way....
Taking address of a reference is not a problem, but it returns pointer to the underlying type, not pointer to reference. Pointers to reference can't be created nor would they make sense since references cannot be rebound. Declaring a pointer to reference type is an error.
The return type T * therefore won't work if T is a reference type. Similarly declaring a mutable T makes no sense if T is a reference type, because references cannot be rebound. So the operator_arrow_proxy is apparently written to expect a non-reference.
If boost instantiates it with reference member of anything, which is always a reference type, it looks like a bug. Indeed, appears to be reported as bug #6554.

Resources