Beginner help with generic dictionary

Hello,
I am a programmer in Delphi, learning C++, I am stuck with the following code, i want to access Fcategorydictionary in the class functions, but i am having errors:


#include <string>
#include <iostream>
#include <list>

using namespace std ;
using namespace System;
using namespace System::Collections::Generic;

typedef Dictionary<String^, String^> MyDictionary;
typedef Dictionary<String^, MyDictionary^> CDictionary;

typedef list<string> ListCatKeys;

ref class CategoryDictionary
{
private :
CDictionary Fcategorydictionary;
bool CatExist(string CatName);
void AddNewCategory(string CatName);
void AddCatValue(string DicKey, string DicValue);
int GetCatDictionaryCount(string CatName);
ListCatKeys GetCatKeys(string CatName);
public :
void Add(string CatName, string DicKey, string DicValue);
void Add(string CatName);
int GetCategoryDicCount(string CatName);
ListCatKeys GetCategoryKeyList(string CatName);
};

int CategoryDictionary::GetCatDictionaryCount(string CatName)
{
MyDictionary^ *aDict;
aDict = Fcategorydictionary[CatName];
PCatDict = &CategoryDictionary.GetDictionary(CatName);
return *aDict.Count;
}
Looks like it is not C++ but a C++/CLI which is distinct language from C++

I believe problem is in line MyDictionary^ *aDict;
What does ^ mean in C++/CLI?
Yes its C++/CLI, since C++ does not recognize using namespace System; which I needed for generics collection.
The ^ punctuator represents a handle
http://www.codeproject.com/Articles/6882/A-first-look-at-C-CLI


All I need, is a way to code a dictionary of dictionaries. I think I can do it in CLI, but I am having these issues.
As I said, C++/CLI is a distinct language. It is not C++. Microsoft should select less misleading name for it.
You could get more luck in Windows programming.

What kind of error do you get? I do not think that managed handle to unmanaged pointer would work.
Also you trying to assign Cdictionary to a pointer to Medictionary.
Well, Visual Studio 2012 is saying Fcategorydictionary cannot be called in CategoryDictionary::GetCatDictionaryCount

Please tell me if there is another way to achieve what I need in C++ ?
and why does Win32 C++ not recognizing using namespace System;
why does Win32 C++ not recognizing using namespace System;
Because there is no headers in standard C++ which place anything into that header.

another way to achieve what I need in C++
1
2
3
4
5
6
7
#include <map>
#include <string>
using StringMap = std::map<std::string, std::string>; //You can use typedefs for this
using Dictionary = std::map<std::string, StringMap>;  //
/*...*/
Dictionary x;
x["foo"]["bar"] = "baz";
Last edited on
Thank you,
I will try to use map and multimap, but I do not think map is as much flexible as generic Dictionary.

generic Dictionary is a nice technology.
And what does it have what cannot be emulated using map?
Well, i have been using Dictionary in Delphi (Embarcadero)

I have started to write with Map, I think Map is the same as generic Dictionary.
I am new to C++, I am trying to understand the different implementation with C++.

I have lot to catch in C++ with CLR, CLI etc.
C++/CLI is not C++. It is another language.
Actually I dislike it: If you want managed enviroment, use C# or Java. There is no need to use a bizzare cross between two different approach.
Ok, I think I am doing something wrong, I kept getting errors when compiling this class.


#ifndef CDICTIONARY_H
#define CDICTIONARY_H

#include <string.h>
#include <iostream>
#include <map>
#include <utility>

using namespace std;

typedef map<string, string> Dictionary;
typedef map<string, Dictionary> CDictionary;

class CategoryDictionary
{
private :
CDictionary CatMap;
CDictionary::iterator CategoryIT;
bool CatExist(string CatName);
void AddNewCategory(string CatName);
public:
void Add(string CatName, string KeyValue, string aValue);
int GetCategoryCount(string CatName);
};

void CategoryDictionary::AddNewCategory(string CatName)
{
Dictionary aDict;
CatMap.insert(pair<string,Dictionary>(CatName, aDict));
}

bool CategoryDictionary::CatExist(string CatName)
{
CategoryIT = CatMap.find(CatName);
if (CategoryIT != CatMap.end)
{
return true;
}
else
{
return false;
}
}

void CategoryDictionary::Add(string CatName, string KeyValue, string aValue)
{
if (!CategoryDictionary::CatExist(CatName))
{
AddNewCategory(CatName);
}

CategoryIT = CatMap.find(CatName);
CategoryIT->second.insert(pair<string, string>(KeyValue, aValue));
}

int CategoryDictionary::GetCategoryCount(string CatName)
{
if (CatExist(CatName) == 1)
{
return CatMap.count(CatName);
}
else
{
return 0;
}
}

#endif
Use code tags when posting code: http://www.cplusplus.com/articles/jEywvCM9/

#include<string> is not the same as #include <string.h> . You need to #include <string> .

if (CategoryIT != CatMap.end) should be if (CategoryIT != CatMap.end()).

Member function definitions which occur in a header file should be inline.
It seems ok, except for this message:
1>------ Build started: Project: ConsoleApplication5, Configuration: Debug Win32 ------
1>Source.obj : error LNK2011: precompiled object not linked in; image may not run
1>D:\Test projects\DictionaryProj\ConsoleApplication5\Debug\ConsoleApplication5.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Why do i have this error :
error C3867: 'CategoryDictionary::GetCategoryCount': function call missing argument list; use '&CategoryDictionary::GetCategoryCount' to create a pointer to member

Why do i need to create a point to member function of a class?
How do you use that function. This error tells that you do not clling this function and it assumes that you want address of function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <string>
#include <iostream>
#include <map>
#include <utility>

using namespace std;

typedef map<string, string> Dictionary;
typedef map<string, Dictionary> CDictionary;
 
class CategoryDictionary
{
	private :
		CDictionary CatMap;
		CDictionary::iterator CategoryIT;
		bool CatExist(string CatName)
		{
			CategoryIT = CatMap.find(CatName);
			if (CategoryIT != CatMap.end())
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		void AddNewCategory(string CatName)
		{
			Dictionary aDict; 
			CatMap.insert(pair<string,Dictionary>(CatName, aDict));	
		}
	public: 
		void Add(string CatName, string KeyValue, string aValue)
		{
			if (!CatExist(CatName))
			{
				AddNewCategory(CatName);
			}
	
			CategoryIT = CatMap.find(CatName);
			CategoryIT->second.insert(pair<string, string>(KeyValue, aValue));
		}
		int GetCategoryCount(string CatName)
		{
			if (CatExist(CatName))
			{		
				CategoryIT = CatMap.find(CatName);
				Dictionary aDict;
				aDict = CategoryIT->second;
				return aDict.count(CatName);
			}
			else
			{
				return 0;
			}
		}
		void PrintCategoryValues(string CatName)
		{
			CategoryIT = CatMap.find(CatName);
			Dictionary aDict;
			aDict = CategoryIT->second;
			for (Dictionary::iterator it=aDict.begin(); it!=aDict.end(); ++it)
				cout << it->first << " => " << it->second << '\n';
	
		}
};


int _tmain()
{
	CategoryDictionary CDict;
	CDict.Add("Cat1","Key1","It is only key one");
	cout << CDict.GetCategoryCount;
	return 0;
}
Is it really that hard to go to the point in the source where the compiler indicates there's an error:

cout << CDict.GetCategoryCount;

and notice that you aren't actually calling the function?

cout << CDict.GetCategoryCount();
yes, sorry, should have been
cout << CDict.GetCategoryCount("Cat1");

yet, i get this error:
1>------ Build started: Project: ConsoleApplication13, Configuration: Debug Win32 ------
1> MainProg.cpp
1>MSVCRTD.lib(crtexe.obj) : error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
1>D:\Test projects\DictionaryProj\ConsoleApplication13\Debug\ConsoleApplication13.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
int _tmain() Probably should be int main(). I assume that you are using MSVS where main function sometimes non-standart
yes, you are right, it should be int main()

the MSVS 2012 is a bit confusing when start to use. i am now understanding how to use it.

at last the class is working perfectly, thank guys.

now, i am going to tackle a thread-safe queue class.
Last edited on
Topic archived. No new replies allowed.