Converting C# Dictionary to C++ map - dictionary

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;
}

Related

String ^ MyString = gcnew String("abcd");

I was reading the c++'s foreach syntax on MSDN:
// for_each_string1.cpp
// compile with: /ZW
#include <stdio.h>
using namespace Platform;
ref struct MyClass {
property String^ MyStringProperty;
};
int main() {
String^ MyString = ref new String("abcd");
for each ( char c in MyString )
wprintf("%c", c);
wprintf("/n");
MyClass^ x = ref new MyClass();
x->MyStringProperty = "Testing";
for each( char c in x->MyStringProperty )
wprintf("%c", c);
}
I tried to find what the "^" means on google but I couldn't find anything (or my query wasn't correct)
What does it mean? Is it as a "*"? Is it as a "&"?
This syntax also applies to C#. Do they mean the same thing in both languages?
Piece of C# code:
using namespace System;
int main(){
array<int>^ arr = gcnew array<int>{0,1,2,5,7,8,11};
int even=0, odd=0;
for each (int i in arr) {
if (i%2 == 0)
even++;
else
odd++;
}
Console::WriteLine(“Found {0} Odd Numbers, and {1} Even Numbers.”,
odd, even);
}
The "^" denotes a managed reference, which is used for managed types. It's like a pointer, but for managed types. The syntax doesn't exist in C#. In C#, the equivalent is just a variable of a reference type (as opposed to a value type), or a boxed value type.
As others have said, this is C++/CLI syntax which means you have to compile with the /clr option. C++/CLI is basically C++ with features of C# (or more generally, .NET).
https://learn.microsoft.com/en-us/cpp/extensions/handle-to-object-operator-hat-cpp-component-extensions?view=vs-2019 hope this link can help you.
btw,^ is a special character and ignored by google search engine so you can not search that.

Adding a System::String^ as key in VC++ Dictionary

I am completely new to C++, so I'm stuck on something which I'm sure is trivial.
I have a dictionary:
Dictionary<String^, Room^>^ roomList = gcnew Dictionary<String^, Room^>();
I'm trying to add a new Room to the dictionary:
Room r("Room 1", x, y);
roomList->Add(r.getName, %r);
Room is defined as follows:
ref class Room
{
private:
String^ mName;
double mX; //scaled X-coordinate of top left corner (meters)
double mY; //scaled Y-coordinate of top left corner (meters)
public:
Room(String^ name, double x, double y);
String ^ const getName() { return mName; }
double const getX() { return mX; }
double const getY() { return mY; }
};
When I try to compile the code I get the following error:
'Room::getName': non-standard syntax; use '&' to create a pointer to member"
What am I doing wrong? For some reason I can't use the object's name (a System::String^) as the key, but I'm not sure why.
roomList->Add(r.getName, %r);
You declared getName as a function, not a property. So it needs to be r.GetName(), note the added () parentheses. Declaring a Name property would be wise, it is the .NET way.
Room r("Room 1", x, y);
This declaration is technically wrong. You are using stack semantics, the r object will automatically be disposed when code execution leaves the scope block. You never want to add a disposed object to a collection. You'll get away with it in this case since you did not actually implement a destructor. Woe be you if you ever do. And woe the reader of your code. Just do it correctly:
Room^ r = gcnew Room("Room 1", x, y);
roomList->Add(r=>getName(), r);
Last but not least, this looks like a student assignment. You cannot get a passing grade for this code, it is not C++. The language you are using is called C++/CLI, it is an extension language that helps writing interop code for .NET programs.

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.

Pass double pointer in a struct to CUDA

I've got the following struct:
struct Param
{
double** K_RP;
};
And I wanna perform the following operations on "K_RP" in CUDA
__global__ void Test( struct Param prop)
{
int ix = threadIdx.x;
int iy = threadIdx.y;
prop.K_RP[ix][iy]=2.0;
}
If "prop" has the following form, how should I do my "cudaMalloc" and "cudaMemcpy" operations?
int main( )
{
Param prop;
Param cuda_prop;
prop.K_RP=alloc2D(Imax,Jmax);
//cudaMalloc cuda_prop ?
//cudaMemcpyH2D prop to cuda_prop ?
Test<<< (1,1), (Imax,Jmax)>>> ( cuda_prop);
//cudaMemcpyD2H cuda_prop to prop ?
return (0);
}
Questions like this get asked from time to time. If you search on the cuda tag, you'll find a variety of examples with answers. Here's one example.
In general, dynamically allocated data contained within structures or other objects requires special handling. This question/answer explains why and how to do it for the single pointer (*) case.
Handling double pointers (**) is difficult enough that most people would recommend "flattening" the storage so that it can be handled by reference with a single pointer (*). If you really want to see how the double pointer (**) method works, review this question/answer. It's not trivial.

Initialising an associative array of struct values and string keys

(for the "D" programming language)
I've been struggling trying to initialise an associative array that has struct elements and should be index-able by a string. I would import it as a module from a separate file.
This is what I want to achieve (and it doesn't work --- I don't know if this is even possible):
mnemonic_info[string] mnemonic_table = [
/* name, format, opcode */
"ADD": {mnemonic_format.Format3M, 0x18},
...
/* NOTE: mnemonic_format is an enum type. */
/* mnemonic_info is a struct with a mnemonic_format and an ubyte */
];
Note that this works fine for arrays indexable by integers.
Optimally, I would like this to be evaluated at compile-time, as I won't be changing it. However, if it's not possible, I would be glad if you told me of the best way to build such an array at/before immediate run-time.
I need this because I'm writing an assembler.
I have searched SO and the internets for an answer, but could only find examples with integers, and other things I didn't understand or couldn't make to work.
I really like D so far but it seems hard to learn due to there not being many tutorials online.
Thanks!
On a side note: is it possible to use Tuples for associative array elements instead of a custom struct?
Edit
There is one way I found so far, but it's pretty ugly:
mnemonic_info[string] mnemonic_table;
static this() { // Not idea what this does.
mnemonic_info entry;
entry.format = mnemonic_format.Format3M;
entry.opcode = 0x18;
mnemonic_table["ADD"] = entry;
/* ... for all entries. */
}
In D, built-in associative array literals are always created in runtime, so initializing a global associative array by assigning it some value at declaration place is currently impossible.
As you found yourself, you can workaround that by assigning a value to associative array in module constructor.
The other problem in your code is struct initialization literals. You should prefer D-style struct initializers to C-style ones.
Example:
struct Foo {
int a;
string b;
}
Foo[string] global;
static this() {
global = [
"foo" : Foo(1, "hurr"),
"bar" : Foo(2, "durr")
];
}
void main() {
assert(global["foo"].a == 1);
}

Resources