fill nested std::map with insert operator - dictionary

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.

Related

Converting C# Dictionary to C++ map

I am receiving a dictionary from a C# dll to C++/CLI code. I am trying to convert dictionary into std::map which will be further used by old C++ code. but I am not able to do. I have a function which is will take dictionary as parameter and return a map.
This is what I am trying to do-
std::map < std::wstring, std::map<int, int>> Convert(Dictionary<String^, Dictionary<int, int>^>^ myMap)
{
std::map < std::wstring, std::map<int, int>> h_result;
for (std::wstring& stringKey : myMap->Keys)
{
for (std::pair<int, int> intKey : (myMap->Values))
{
h_result.insert(stringKey, intKey);
}
}
return h_result;
}
I am getting error while iterating the values.
error:this range-based 'for' statement requires a suitable "begin" function and none was found
Can anybody tell what is the problem here? or if there is any better way to convert Dictionary^ into std::map, please do suggest me.
I am new with dictionary and std::map. please let me know if there is any silly mistake with the sample code.
You're (a) trying to use C++ range-for loops with Dictionary^, and (b) trying to use System types interchangeably with C++ standard types. All of which won't work.
You need to do this a bit more step-by-step: iterate the Dictionary^ collections with for each, convert the String^ to std::wstring properly, and create the map items with std::make_pair.
So your function will look something like this (untested)
std::map <std::wstring, std::map<int, int>> Convert(Dictionary<String ^, Dictionary<int, int>^> ^myMap)
{
std::map <std::wstring, std::map<int, int>> h_result;
// iterate the outer dictionary
for each(KeyValuePair<String ^, Dictionary<int, int>^> ^kvp1 in myMap)
{
std::wstring stringKey = marshal_as<std::wstring>(kvp1->Key);
std::map<int, int> mapValues;
// iterate the inner dictionary
for each(KeyValuePair<int, int> ^kvp2 in kvp1->Value)
{
// insert in inner map
mapValues.insert(std::make_pair(kvp2->Key, kvp2->Value));
}
// insert in outer map
h_result.insert(std::make_pair(stringKey, mapValues));
}
return h_result;
}

How to use C++11 range-based for with QJsonArray

With old-style loops, I can delve into a QJsonArray and, in the example below, add element "foo" with contents of existing element "bar" for each array item. How can I do this using C++11 range-based for?
// QJsonArray oldArray contains an array of which one element is "bar"
QJsonArray newArray;
int i, b = oldArray.count();
for (i=0; i<n; ++i) {
QJsonObject element = oldArray.at(i).toObject();
element["foo"] = element["bar"];
newArray.append(element);
}
I have tried the following (admittedly as trial and error):
auto&
for (auto& element : oldArray) {
element["foo"] = element["bar];
newArray.append(element);
}
I get the error
non-const lvalue reference to type 'QJsonValueRef' cannot bind to a temporary of type 'QJsonValueRef'
const auto&
for (const auto& element : oldArray) {
...
I get a warning
loop variable 'element' is always a copy because the range of type 'QJsonArray' does not return a reference
const auto
for (const auto element : oldArray) {
element["foo"] = element["bar];
...
I get the error
no viable overloaded operator[] for type 'const QJsonValueRef'
relating to element["bar"]
The problem is that the iterator for QJsonArray returns a temporary QJsonValueRef object, and lvalue references can not bind to temporaries. We can either hold that temporary by value:
// QJsonArray oldArray contains an array of which one element is "bar"
QJsonArray newArray;
for (auto v : oldArray) {
QJsonObject element = v.toObject();
element["foo"] = element["bar"];
newArray.append(element);
}
In this case v is a QJsonValueRef object (similar to what oldArray.at(i) gives in the old-style loop). After that, we convert that QJsonValueRef to a QJsonObject using .toObject().
Or we can use forwarding references since they can bind to rvalues:
for (auto&& v : oldArray) {
...
}
In this case v is deduced to be an rvalue reference to a QJsonValueRef.
Both solutions are identical in terms of the number of objects being created/destructed (since in the former, the copy is elided under C++17 guaranteed copy elision rules or even in pre-C++17 when using any decent compiler. In the latter, the reference is bound to the temporary and this prolongs its lifetime to match the whole iteration).
Notes
This problem is similar to what happens when using range-based-for with a std::vector<bool>; since both std::vector<bool> and QJsonArrayhave iterators that return proxy objects.
If using the Clang code model, the second solution generates the warning "loop variable 'v' is always a copy because the range of type 'QJsonArray' does not return a reference". See this question for an explanation.

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;

foreach not working on list of QPair

Using Qt, I want this code to work:
QList<QPair<QString, QString>> list;
foreach (QPair<QString, QString> pair, list)
{
}
instead, I get the error:
'pair' : undeclared identifier
Using a typedef I can make it work, but this is not what I want (unless this is the only thing that works):
typedef QPair<QString, QString> MyPair;
QList<MyPair> list;
foreach (MyPair pair, list)
{
}
Can anyone explain why the first foreach doesn't compile?
it's not the foreach error. It's declaration error. You declared list like this:
QList<QPair<QString, QString>> list;
while it should this way:
QList<QPair<QString, QString> > list;
Just declare QPair outside of loop:
QPair<QString,QString> pair;
foreach(pair,list){
}
It is not possible to use template classes inside qt foreach statement which contains more than one template parameter, because comma separator conflicts with comma separator inside macros.
#define add( a, b ) (a + b)
template < typename T1, typename T2 >
struct DATA
{
static const T1 val1 = 1;
static const T2 val2 = 2;
};
// Usage
const int c = add( 1, 2 ); // OK
const int d = add( DATA< int, int >::val1 , DATA< int, int >::val2 ); // FAIL
because macros add will interpret "DATA< int" as first argument, and " int >::val1" as second, and so on.
Some explanation with above answer... if your compiler accept
QList<QPair<QString, QString>> list;
giving no error on such declaration, reasons for topic caster error is different and indeed has to do with a fact that declaration must be done outside of foreach() loop. That's explained in QT documentation.
regarding >> and > >... that's old story and latest GCC (so linux/mac) consider it to be a syntax mistake, because it's not conforming standard. >> in GCC manner is treated as operator with all follow-up errors..

How can I store function pointer in vector?

like: vector<void *(*func)(void *)>...
You can declare a vector of pointers to functions taking a single void * argument and returning void * like this:
#include <vector>
std::vector<void *(*)(void *)> v;
If you want to store pointers to functions with varying prototypes, it becomes more difficult/dangerous. Then you must cast the functions to the right type when adding them to the vector and cast them back to the original prototype when calling. Just an example how ugly this gets:
#include <vector>
int mult(int a) { return 2*a; }
int main()
{
int b;
std::vector<void *(*)(void *)> v;
v.push_back((void *(*)(void *))mult);
b = ((int (*)(int)) v[0])(2); // The value of b is 4.
return 0;
}
You can use typedef's to partially hide the function casting syntax, but there is still the danger of calling a function as the wrong type, leading to crashes or other undefined behaviour. So don't do this.
// shorter
std::vector<int (*)(int)> v;
v.push_back(mult);
b = v[0](2); // The value of b is 4.
Storing a function in vector might be a difficult task as illustrated above. In that case if u want to dynamically use a function u can also store a function in pointer which is much easier. Main advantage of this is u can store any type of function either it is a normal function or a paramatrized one(having some input as parametrs). Complete process is described in the link given below with examples...just have a look...!!!
how can we store Function in pointer

Resources