I'm developing a container template class. This code needs to interface with existing C code and needs to stay binary compatible, so I can not use i.e. std::vector or similar.
The problem that I have is that it needs to support different allocation strategies, and I don't know how to provide the allocator as a template argument. I created an SSCCE to illustrate how far I got (which of course doesn't compile, because if it would, I wouldn't need to ask this question :)).
#include <iostream>
#include <cstring>
#include <type_traits>
typedef unsigned int uint_t;
typedef signed int int_t;
template <typename T, typename S, typename _allocator = _virtual>
class Container
{
public:
Container(S nItems = 0, S nMaxItems = 0, T *pArray = NULL)
{
mItems = nItems;
mMaxItems = nMaxItems;
mArray = pArray;
}
void adjustMalloc(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T));
mMaxItems += nClusterSize;
}
}
void adjustAligned(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)_aligned_realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), 16);
mMaxItems += nClusterSize;
}
}
void adjustVirtual(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = VirtualAlloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), MEM_RESERVE, PAGE_NOACCESS);
mMaxItems += nClusterSize;
}
}
void adjust(uint_t nClusterSize)
{
if (std::is_same<_allocator>::value == _virtual)
adjustVirtual(nClusterSize);
else if(std::is_same<_allocator>::value == _aligned)
adjustAligned(nClusterSize);
else if(std::is_same<_allocator>::value == _malloc)
adjustMalloc(nClusterSize);
else
{
// Cause a static compiler error, how?
}
}
bool add(T *pItem)
{
if(find(pItem) == NULL)
{
adjust(100);
mItems++;
return true; // added
}
return false;
}
T *find(T *pItem)
{
T *p = mArray;
for(S i = 0; i < mItems; i++, p++)
{
if(*p == *pItem)
return p;
}
return NULL;
}
private:
S mItems;
S mMaxItems;
T *mArray;
};
class Record
{
public:
bool operator==(const Record &oRecord)
{
if(Id != oRecord.Id)
return false;
if(strcmp(Name, oRecord.Name) != 0)
return false;
return true;
}
int Id;
char Name[10+1];
};
int main(int argc, char *argv[])
{
Record rec;
rec.Id = 0;
strcpy(rec.Name, "Test");
Container<Record, uint_t> records; // Default using malloc
records.add(&rec);
if(records.find(&rec) == NULL)
std::cerr << "Not found" << std::endl;
Container<Record, uint_t, _virtual> vrecords; // VirtualAlloc allocator used.
vrecords.add(&rec);
if(records.find(&rec) == NULL)
std::cerr << "Not found" << std::endl;
return 0;
}
I'm using Visual Studio 2010 so it's not 100% C++11.
The VirtualAlloc is provided just as (another) example and will not work as it is shown here.
I found a solution for my problem. However, I get warnings
warning C4127: conditional expression is constant
in the adjust() method for the if(std::is_same... and I was wondering if this is normal or if I can get rid of it, other than disabling it.
#include "stdafx.h"
#include "windows.h"
#include <iostream>
#include <cstring>
#include <type_traits>
#pragma warning (push)
//#pragma warning (disable : 4127)
typedef unsigned int uint_t;
typedef signed int int_t;
typedef struct { const static bool _virtual_allocator = true; } _virtual_type;
typedef struct { const static bool _aligned_allocator = true; } _aligned_type;
typedef struct { const static bool _malloc_allocator = true; } _malloc_type;
template <typename T, typename S, typename _allocator = _aligned_type>
class Container
{
public:
Container(S nItems = 0, S nMaxItems = 0, T *pArray = NULL)
{
mItems = nItems;
mMaxItems = nMaxItems;
mArray = pArray;
}
void adjustMalloc(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T));
mMaxItems += nClusterSize;
}
}
void adjustAligned(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)_aligned_realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), 16);
mMaxItems += nClusterSize;
}
}
void adjustVirtual(uint_t nClusterSize)
{
if(mItems == mMaxItems)
{
mArray = (T *)VirtualAlloc((LPVOID)mArray, (mMaxItems+nClusterSize)*sizeof(T), MEM_RESERVE, PAGE_NOACCESS);
mMaxItems += nClusterSize;
}
}
void adjust(uint_t nClusterSize)
{
if (std::is_same<_allocator, _virtual_type>::value)
adjustVirtual(nClusterSize);
else if(std::is_same<_allocator, _aligned_type>::value)
adjustAligned(nClusterSize);
else if(std::is_same<_allocator, _malloc_type>::value)
adjustMalloc(nClusterSize);
else
{
// Cause a static compiler error, how?
}
}
bool add(T *pItem)
{
if(find(pItem) == NULL)
{
adjust(100);
mItems++;
return true; // added
}
return false;
}
T *find(T *pItem)
{
T *p = mArray;
for(S i = 0; i < mItems; i++, p++)
{
if(*p == *pItem)
return p;
}
return NULL;
}
private:
S mItems;
S mMaxItems;
T *mArray;
};
#pragma warning (pop)
class Record
{
public:
bool operator==(const Record &oRecord)
{
if(Id != oRecord.Id)
return false;
if(strcmp(Name, oRecord.Name) != 0)
return false;
return true;
}
int Id;
char Name[10+1];
};
int main(int argc, char *argv[])
{
Record rec;
rec.Id = 0;
strcpy(rec.Name, "Test");
Container<Record, uint_t> mrecords;
mrecords.add(&rec);
if(mrecords.find(&rec) == NULL)
std::cerr << "Malloc Not found" << std::endl;
Container<Record, uint_t, _aligned_type> arecords;
arecords.add(&rec);
if(arecords.find(&rec) == NULL)
std::cerr << "Aligned Not found" << std::endl;
Container<Record, uint_t, _virtual_type> vrecords;
vrecords.add(&rec);
if(vrecords.find(&rec) == NULL)
std::cerr << "Virtual Not found" << std::endl;
return 0;
}
Related
I use Google’s dense_hash_map as a cache of some data. When I use the find function to find a key, I find that it doesn’t exist, but when traversing dense_hash_map, I can see that the key exists. Is it wrong where I used it? By the way, I have rewritten the EqualKey class required by dense_hash_map.
This is my test code:
class StringVal {
public:
StringVal(string &str) {
len = str.length();
ptr = new uint8_t[len];
memcpy(ptr, str.c_str(), len);
}
StringVal(uint8_t* ptr = NULL, int len = 0) : len(len), ptr(ptr) {
if(ptr == NULL) {
is_null = NULL;
}
}
StringVal(const char* ptr) : len(strlen(ptr)),ptr(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(ptr))) {
if(ptr == NULL) {
is_null = NULL;
}
}
~StringVal() {
delete[] ptr;
}
uint8_t* ptr;
int len;
bool is_null;
static StringVal null() {
StringVal sv;
sv.is_null = true;
return sv;
}
bool operator==(const StringVal& other) const {
if (is_null != other.is_null) return false;
if (is_null) return true;
if (len != other.len) return false;
return ptr == other.ptr || memcmp(ptr, other.ptr, len) == 0;
}
bool operator!=(const StringVal& other) const { return !(*this == other); }
};
struct NewStringValCmp {
bool operator()(const StringVal* s1, const StringVal* s2) const {
if (s1 == NULL && s2 == NULL) return 1;
if (s1 == NULL || s2 == NULL) return 0;
if (s1->is_null != s2->is_null) return false;
if (s1->is_null) return true;
if (s1->len != s2->len) return false;
return memcmp(s1->ptr, s2->ptr, s1->len) == 0;
}
};
typedef dense_hash_map<StringVal*, StringVal*, std::hash<StringVal*>, NewStringValCmp> new_dict_map_string_t;
vector<string> data = {
"test1","1",
"test2","2",
"test3","3",
"test4","4",
"test5","5",
"test6","6",
"test7","7",
"test8","8",
"test9","9",
"test10","10"
};
int main() {
new_dict_map_string_t* cm = new new_dict_map_string_t();
cm->set_empty_key(NULL);
for (int i = 0; (i + 1) < data.size(); i+=2) {
StringVal *key = new StringVal(data[i]);
StringVal *value = new StringVal(data[i+1]);
(*cm)[key] = value;
}
string input = "";
while (1) {
cin >> input;
if (input == "q") {
break;
}
StringVal *target = new StringVal(input);
for (auto itor: *cm) {
if (*(itor.first) == *target) {
cout << "find target" << endl;
}
}
auto itor = cm->find(target);
if (itor == cm->end()) {
cout << "cm->find nothing" << endl;
} else {
cout << itor->second->ptr << endl;
}
delete target;
input = "";
}
for (auto iter : *cm) {
delete iter.first;
delete iter.second;
}
delete cm;
return 0;
}
I am getting this error message can anyone help me out.
I am getting the error code 'return' cannot convert from 'clsStack' to 'T' relating the two functions listed below.
Code is as follows
Class
template <class T>
class clsStack //this is the stack class that is used to handle the functions and any data that needs passing between functions
{
private:
clsStack* data;
int iTop;
int iSize;
void resize();
bool needToResize();
string sExpresion;
public:
void stack()
{
iSize = 5;
iTop = 0;
data = new clsStack[iSize];
}
void push(T item);
T peek();
T pop();
bool isEmpty();
};
The two functions I think the issue is related to
template <class T>
T clsStack<T>::peek() //this is used to look at the last number is the array
{
if (iTop <= 0)
throw out_of_range("Attempted to peek an empty stack. \n");
return data[iTop - 1];
}
template <class T>
T clsStack<T>::pop()
{
if (iTop <= 0)
throw out_of_range("Attempted to pop an empty stack. \n");
iTop++;
return data[iTop];
}
The main function where these functions are been called
int evaluate(string sExpresion)
{
clsStack<int> iValues;
clsStack<char> cOperators;
int iValue = 0;
int iPosition = 0;
bool bResult = false;
while (iPosition < sExpresion.length())
{
char cSpot = sExpresion[iPosition];
if (isDigit(cSpot))
{
iValue = (iValue * 10) + (int)(cSpot - '0');
}
else if (isOperator(cSpot))
{
if (cSpot == '(')
{
cOperators.push(cSpot);
iValue = 0;
}
if (cSpot == '-')
{
cOperators.push(cSpot);
iValue = 0;
}
else if (iValues.isEmpty() && cOperators.peek() == '-')
{
int iPrevValue = iValues.pop();
int iPrevOperator = cOperators.pop();
iPrevValue = operation(iValue, iPrevValue, iPrevOperator);
iValues.push(iPrevValue);
cOperators.push(cSpot);
}
else if (iValues.isEmpty())
{
iValues.push(iValue);
cOperators.push(cSpot);
iValue = 0;
}
else if (cSpot == ')')
{
iValues.push(iValue);
while (cOperators.peek() != '(')
{
cSpot = cOperators.pop();
iValue = iValues.pop();
int iPrev = iValues.pop();
iValue = operation(iPrev, iValue, cSpot);
iValues.push(iValue);
}
cOperators.pop();
iValues.pop();
}
else
{
int iPrevValue = iValues.pop();
int iPrevOperator = cOperators.pop();
iPrevValue = operation(iPrevValue, iValue, iPrevOperator);
iValues.push(iPrevValue);
cOperators.push(cSpot);
iValue = 0;
}
}
iPosition++;
}
while (!cOperators.isEmpty())
{
int iPrev = iValues.pop();
char cSpot = cOperators.pop();
iValue = operation(iPrev, iValue, cSpot);
bResult = true;
}
return (sExpresion, iValue, bResult);
}
Any help is much apricated.
I have method of class Stack, which compares 2 objects of this class:
bool comparison(T &stack) {
if (size == stack.size)
for (int i = 0; i < size; i++) {
if (!this->stackPr[i].comparison(stack.stackPr[i]))
return false;
}
else
return false;
return true;
}
and uses the method of class Time:
bool comparison(Time &time) {
if ((this->hours == time.hours) && (this->minutes == time.minutes) && (this->seconds == time.seconds))
return true;
return false;
When I try to use this comman in main:
bool temp = stack3.comparison(stack4);
MVS underlines |stack4| and shows me the error:
a reference of type "Time &"(non-const qualified) cannot be initialized with a value of type Stack<Time>
How could I handle this problem?
Thanks for your answers :)
There is class Stack:
class Stack {
private:
T *stackPr;
int size;
int top;
public:
//----------------CONSTRUCTORS-----------------
Stack(int n) {
if (n > 0)
size = n;
else
size = 10;
stackPr = new T[size];
top = -1;
}
Stack() {
size = 10;
stackPr = new T[size];
top = -1;
}
Stack(Stack &stack) {
stackPr = new T[stack.size];
size = stack.size;
top = stack.top;
for (int i = 0; i < size; i++)
stackPr[i] = stack.stackPr[i];
}
Stack(T *objs, int sizeMass) {
size = sizeMass;
stackPr = new T[size];
for (int i = 0; i < sizeMass; i++) {
this->push(objs[i]);
}
}
//----------------DESTRUCTOR-------------------
~Stack() {
delete[] stackPr;
}
//-----------------METHODS---------------------
//Add element to stack
void push(T &element) {
if (top == size - 1)
cout << "\nThere's no more place!!!\n";
else {
top++;
stackPr[top] = element;
cout << "\nElement was succesfully pushed\n";
}
}
//Read + Delete
T pop() {
if (top == -1)
cout << "\nStack is empty\n";
else {
T temp = stackPr[top];
stackPr[top] = 0;
top--;
cout << "\nElement was succesfully poped and deleted\n";
return temp;
}
}
//Read
T popup() {
if (top == -1)
cout << "\nStack is empty\n";
else {
cout << "\nElement was succesfully popped\n";
return stackPr[top];
}
}
//Comparison of 2 stacks
bool comparison(T &stack) {
if (size == stack.size)
for (int i = 0; i < size; i++) {
if (!this->stackPr[i].comparison(stack.stackPr[i]))
return false;
}
else
return false;
return true;
}
};
Try this, in your Stack class
change:
bool comparison(T &stack) {
for this:
bool comparison(Stack<T> &stack) {
First of all, abandon this comparison function, it hinders your code, use == instead.
Secondly, use const Stack<T> in your comparison function.
And finally, use auto to deduce the type of the variables.
Here is an example that shows the basics of what I just wrote:
#include <iostream>
using namespace std;
struct Time
{
bool operator==(const Time& time)
{
return true;// adjust it with your own needs.
}
};
template<typename T>
struct Stack
{
T val;
Stack(T& val_): val(val_) {}
bool operator==(const Stack<T>& stack)
{
return this->val == stack.val; // here is your business logic of comparison
}
};
int main()
{
Time t1;
Time t2;
Stack<Time> myStack1(t1);
Stack<Time> myStack2(t2);
auto temp = myStack1 == myStack2;
cout << temp << endl;
return 0;
}
Here's the code :
The place where it crashed is marked with a comment(//////crash).
I don't know what results in the problem.
After I print the size of data got from file,It shows '1' means that the array should only contains 1 element. So it seems that there's no 'bad_allocate error' ...
Could you guys help me ? I would appreciate your kindly help very much. :)
#include<stdio.h>
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<string.h>
#include<type_traits>
using namespace std;
bool read_int(int& val,FILE*& fp)
{
if(fp == nullptr)
return false;
fread(&val,sizeof(int),1,fp);
return true;
}
bool write_int(int val,FILE*& fp)
{
if(fp == nullptr)
{
return false;
}
fwrite(&val,sizeof(int),1,fp);
return true;
}
struct SANOBJ
{
char path[128];
char nickname[40];
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
if(_p == nullptr || _n == nullptr)
*this = {};
int m = strlen(_p),n = strlen(_n);
if(m < 128) strcpy(path,_p);
if(n < 40) strcpy(nickname,_n);
}
~SANOBJ(){}
SANOBJ(const SANOBJ& other)
{
memcpy(path,other.path,sizeof(char) * 128);
memcpy(nickname,other.nickname,sizeof(char) * 40);
}
bool operator < (const SANOBJ& other) const
{
return string(path) < string(other.path);
}
bool operator == (const SANOBJ& other) const
{
return (strcmp(other.path,path) == 0);
}
};
template <typename source_type> //the 'source_type' type need to have the member 'int m_index'
class FrameQueue
{
public:
FrameQueue() //fill the 1st frame automatically
{
source_type new_node;
new_node.m_index = 0;
m_data.push_back(new_node);
}
FrameQueue(const FrameQueue& other)
{
m_data = other.m_data;
}
bool AddFrame(const source_type& other) // keeps an ascending order
{
int index = _binary_search(other);
if(index != -1)
{
return false;
}
m_data.insert(std::upper_bound(m_data.begin(),m_data.end(),other,
[](const source_type& a,const source_type& b)->bool const{return a.m_index < b.m_index;}
),other);
return true;
}
bool DeleteFrameByElemIndex(int elemIndex) //delete frame according to the index of frame in the queue
{
if(elemIndex < 0)
return false;
if(elemIndex >= m_data.size())
return false;
typename std::vector<source_type>::iterator it ;
it = m_data.begin() + elemIndex;
it = m_data.erase(it);
return true;
}
bool DeleteFrameByFrameIndex(int frameIndex)
{
source_type node = {};
node.m_index = frameIndex;
int index = _binary_search(node);
if(index == -1)
{
return false;
}
typename std::vector<source_type>::iterator it;
it = m_data.begin() + index;
it = m_data.erase(it);
return true;
}
bool Clear() // There would always be a single frame
{
source_type new_node = {};
new_node.m_index = 0;
m_data.clear();
m_data.push_back(new_node);
return true;
}
bool WriteFile(FILE*& fp)
{
if(fp == nullptr)
return false;
bool result = write_int(m_data.size(),fp);
if(result == false)
return false;
fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
return true;
}
bool ReadFile(FILE*& fp)
{
if(fp == nullptr)
return false;
int data_size;
bool result = read_int(data_size,fp);
if(result == false)
return false;
if(data_size > 0)
{
m_data.resize(data_size);
fread(&(m_data[0]),sizeof(source_type),data_size,fp);
}
return true;
}
private:
int _binary_search(source_type target)
{
int l = 0,r = (int)m_data.size() - 1,mid;
while(l<=r)
{
mid = (l + r) / 2;
if(m_data[l].m_index == target.m_index)
{
return l;
}
if(m_data[r].m_index == target.m_index)
{
return r;
}
if(m_data[mid].m_index == target.m_index)
{
return mid;
}
if(m_data[mid].m_index > target.m_index)
{
r = mid - 1;
}
else
{
l = mid + 1;
}
}
return -1;
}
public:
vector<source_type> m_data;
};
template<typename source_type>
class UniqueSource
{
public:
UniqueSource(){}
~UniqueSource(){}
bool Add(const source_type& other)//return false when insert failed,otherwise return true
{
if(m_map_source_to_index.find(other) == m_map_source_to_index.end())
{
int map_size = m_map_source_to_index.size();
m_data.push_back(other);
m_map_source_to_index.insert(pair<source_type,int>(other,map_size));
m_result.push_back(map_size);
return true;
}
else
{
m_result.push_back(m_map_source_to_index[other]);
return true;
}
return false;
}
bool Delete(int elemIndex) // delete the elem by elem Index,If succeed ,return true,otherwise return false
{
if(elemIndex < 0)
return false;
if(elemIndex >= m_data.size())
return false;
typename std::map<source_type,int>::iterator mit;
typename std::vector<source_type>::iterator vit;
for(mit = m_map_source_to_index.begin();mit!=m_map_source_to_index.end();++mit)
{
m_map_source_to_index.erase(mit);
}
vit = m_data.begin() + elemIndex;
m_data.erase(vit);
return true;
}
bool Clear()
{
m_map_source_to_index.clear();
m_data.clear();
m_result.clear();
return true;
}
bool WriteFile(FILE*& fp)
{
if(fp == nullptr)
return false;
bool result = write_int(m_data.size(),fp);
if(result == false)
return false;
if(m_data.size() > 0)
fwrite(&(m_data[0]),sizeof(source_type),m_data.size(),fp);
result = write_int(m_result.size(),fp);
if(result == false)
return false;
if(m_result.size() > 0)
fwrite(&(m_result[0]),sizeof(int),m_result.size(),fp);
return true;
}
bool ReadFile(FILE*& fp)
{
if(fp == nullptr)
return false;
Clear();
int data_size;
read_int(data_size,fp);
if(data_size > 0)
{
printf("[%d]",data_size);
m_data.resize(data_size); /////////////////Crash!!!!!!!!!!!!
printf("Resize Ok\r\n");
fread(&(m_data[0]),sizeof(source_type),data_size,fp);
}
read_int(data_size,fp);
printf("[%d]",data_size);
if(data_size > 0)
{
m_result.resize(data_size);
fread(&(m_result[0]),sizeof(int),data_size,fp);
}
return true;
}
//private:
map<source_type,int> m_map_source_to_index;
vector<source_type> m_data;
vector<int> m_result; //the index I want
};
int main()
{
UniqueSource<SANOBJ> m;
SANOBJ t = {"123","456"};
m.Add(t);
printf("Added\r\n");
FILE* fp = nullptr;
fp = fopen("test.b","wb");
if(fp == nullptr)
{
printf("Failed...\r\n");
}
bool ret = false;
ret = m.WriteFile(fp);
if(ret)
{
printf("Writed!\r\n");
fclose(fp);
}
fp = fopen("test.b","rb");
if(fp == nullptr)
{
printf("Failed...\r\n");
}
ret = m.ReadFile(fp);
fclose(fp);
printf("Readed\r\n");
for(int i=0;i<m.m_data.size();i++)
printf("%s %s\r\n",m.m_data[i].path,m.m_data[i].nickname);
return 0;
}
*this = {} default-constructs a new SANOBJ instance and then assigns it to *this. This would normally be OK, but here you are calling it from the SANOBJ default constructor (making the logic being something like "to default-construct a SANOBJ, default-construct a SANOBJ and then assign its value to myself"), leading to infinite recursion and eventually a stack overflow.
Sidenote: The copy constructor is not needed.
Yes. The problem is is with *this = {}
If I were you, I'd rewrite SANOBJ constructor like this (this is a rough code and you may need to slightly modify it if you wish)
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
{
if (( _p != nullptr ) && ((strlen(_p) < 128)))
strcpy(path,_p);
if (( _n != nullptr ) && ((strlen(_n) < 40)))
strcpy(nickname,_n);
}
It'll resolve the problem.
Naturally, I don't play with *this (not this).
If you want to be sure that the member variables are empty (char path[128] and char nickname[40])
set at the beginning of the constructor something like:
path[0] = '\0';
nickname[0] = '\0';
Or use something like on constructor:
SANOBJ(const char* _p = nullptr,const char* _n = nullptr)
: path(), nickname()
{
}
But don't use *this= {}
So I have such definition on map class on vector, it works good except for post-incrementation, which doesn't work as it should. You can see in example that variable a should be equal to 10 (post-incremented after assignment). But it's equal to 11. I have no idea how to fix that.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
template<class T>
class Map {
class Cref {
friend class Map;
Map& m;
string key;
T value;
public:
operator double() {
return m.read(key);
};
Map::Cref & operator=(double num) {
m.write(key, num);
return *this;
};
Map::Cref & operator++(int) {
Cref c(*this);
m.increment(key, value);
return c;
}
Cref(Map& m, string a)
: m(m),
key(a) {};
};
public:
class Unitialized {};
struct Record {
string key;
T value;
};
vector<Record> data;
Map() {}
~Map() {}
bool ifexist(string k) {
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == k)
return 1;
}
return 0;
}
Cref operator[](string key) {
return Map::Cref( * this, key);
}
private:
void increment(string key, T value) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
data.at(i).value += 1;
}
}
void write(string key, T value) {
if (ifexist(key) == 1) {
cout << "Element already exist" << endl;
return;
}
Record r;
r.key = key;
r.value = value;
data.push_back(r);
}
double read(string key) {
if (ifexist(key) == 0) {
throw Unitialized();
}
for (int i = 0; i < data.size(); i++) {
if (data.at(i).key == key)
return data.at(i).value;
}
return 0;
}
};
int main(int argc, char** argv) {
Map<int> m;
m["ala"] = 10;
int a = 0;
a = m["ala"]++;
cout << a << endl;
try {
cout << m["ala"] << endl;
cout << m["ola"] << endl;
} catch (Map<int>::Unitialized&) {
cout << "Unitialized element" << endl;
}
return 0;
}
Yes, I already fixed that, overloading of ++ operator should look like that :
T operator ++(int)
{
T ret = m.read(this->key);
m.increment(key, value);
return ret;
}
This fixes everything.