STL MAP, how to restrict

H

Haro Panosyan

#include <iostream>
#include <map>
#include <string>

using namespace std;


void InitMap( map<string, int>& Map)
{
Map["aa"] = 0;
Map["bb"] = 0;
}

int main() {

map<string, int> MyMap;

InitMap( MyMap);

MyMap["aa"] = 10;// Questione 1

MyMap["cc"] = 20;// Question 2

map<string, int>::const_iterator iter;
for (iter=MyMap.begin(); iter != MyMap.end(); iter++) {
cout << iter->first << " " << iter->second << endl;
}

return 0;

}


Question 1:

How do I create my own map, which would allow me to check during

MyMap["aa"] = 10;

that values for "aa" can be from 0 to 5, so the above assignment
would print error message.


Question 2:

How do I prevent my map to be only 2 elements, "aa" and "bb", so
creation of new element "cc" would not be allowed.

Thanks,
-haro
(I tried and failed, I googled and failed, so I came here.
Please excuse if this is very simple or discribed somewhere)
 
V

Victor Bazarov

Haro said:
#include <iostream>
#include <map>
#include <string>

using namespace std;


void InitMap( map<string, int>& Map)
{
Map["aa"] = 0;
Map["bb"] = 0;
}

int main() {

map<string, int> MyMap;

InitMap( MyMap);

MyMap["aa"] = 10;// Questione 1

MyMap["cc"] = 20;// Question 2

map<string, int>::const_iterator iter;
for (iter=MyMap.begin(); iter != MyMap.end(); iter++) {
cout << iter->first << " " << iter->second << endl;
}

return 0;

}


Question 1:

How do I create my own map, which would allow me to check during

MyMap["aa"] = 10;

that values for "aa" can be from 0 to 5, so the above assignment
would print error message.


Question 2:

How do I prevent my map to be only 2 elements, "aa" and "bb", so
creation of new element "cc" would not be allowed.

Thanks,
-haro
(I tried and failed, I googled and failed, so I came here.
Please excuse if this is very simple or discribed somewhere)

What you seem to need is a "wrapper" for 'std::map'. Since your
own 'map' is not an extension of 'std::map' (you want to impose
limitations on 'std::map' contents, which means your map is not
a std::map in the pure OO sense, see LSP), you should consider
private inheritance and re-implementation of the interface with
pre- and post-conditions verified in your implementations.

V
 
N

Noah Roberts

Haro said:
How do I create my own map, which would allow me to check during

MyMap["aa"] = 10;

that values for "aa" can be from 0 to 5, so the above assignment
would print error message.


Question 2:

How do I prevent my map to be only 2 elements, "aa" and "bb", so
creation of new element "cc" would not be allowed.

It sounds to me like a map is totally inappropriate for your needs.
You should consider a different container or even no container at all.
You're using none of map's features.
 
M

mlimber

Haro said:
#include <iostream>
#include <map>
#include <string>

using namespace std;


void InitMap( map<string, int>& Map)
{
Map["aa"] = 0;
Map["bb"] = 0;
}

int main() {

map<string, int> MyMap;

InitMap( MyMap);

MyMap["aa"] = 10;// Questione 1

MyMap["cc"] = 20;// Question 2

map<string, int>::const_iterator iter;
for (iter=MyMap.begin(); iter != MyMap.end(); iter++) {
cout << iter->first << " " << iter->second << endl;
}

return 0;

}


Question 1:

How do I create my own map, which would allow me to check during

MyMap["aa"] = 10;

that values for "aa" can be from 0 to 5, so the above assignment
would print error message.

Create a class that does range checking and automatically converts to
and from int, e.g. (untested code):

#include <map>
#include <string>
#include <exception>

template<typename T, T lower, T upper>
class RangeCheckedVal
{
T val_;

static T Validate( const T& val )
{
if( val < lower || val > upper )
{
throw std::range_error( "Value out of range" );
}
return val;
}

public:
RangeCheckedVal( const T& val = lower )
: val_( Validate(val) )
{}

operator T() const { return val_; }
};

int main()
{
std::map<std::string, RangeCheckedVal<int,0,5> > myMap;
myMap[ "aa" ] = 5; // ok
myMap[ "bb" ] = 10; // throws an exception
}
Question 2:

How do I prevent my map to be only 2 elements, "aa" and "bb", so
creation of new element "cc" would not be allowed.

Make the map const. To do this, you'd need to initialize the class on
declaration somehow, e.g.:

template<class K, class V>
class MapInitializer
{
typedef std::map<K,V> Map;
Map m_;
public:
operator Map() const { return m_; }

MapInitializer& Add( const K& k, const V& v )
{
m_[k] = v;
return *this;
}
};

const std::map<std::string,int> myMap
= MapInitializer<std::string, int>()
.Add( "aa", 9 )
.Add( "bb", 42 );

Of course, if the map is const, the [] operator won't work (outside the
initializer) since it inserts a key/value pair if one doesn't exist,
but std::map::find() is safer anyway.

Cheers! --M
 
H

Haro Panosyan

Please find my comments bellow inserted.
Haro said:
#include <iostream>
#include <map>
#include <string>

using namespace std;


void InitMap( map<string, int>& Map)
{
Map["aa"] = 0;
Map["bb"] = 0;
}

int main() {

map<string, int> MyMap;

InitMap( MyMap);

MyMap["aa"] = 10;// Questione 1

MyMap["cc"] = 20;// Question 2

map<string, int>::const_iterator iter;
for (iter=MyMap.begin(); iter != MyMap.end(); iter++) {
cout << iter->first << " " << iter->second << endl;
}

return 0;

}


Question 1:

How do I create my own map, which would allow me to check during

MyMap["aa"] = 10;

that values for "aa" can be from 0 to 5, so the above assignment
would print error message.


Create a class that does range checking and automatically converts to
and from int, e.g. (untested code):

#include <map>
#include <string>
#include <exception>

template<typename T, T lower, T upper>
class RangeCheckedVal
{
T val_;

static T Validate( const T& val )
{
if( val < lower || val > upper )
{
throw std::range_error( "Value out of range" );
}
return val;
}

public:
RangeCheckedVal( const T& val = lower )
: val_( Validate(val) )
{}

operator T() const { return val_; }
};

int main()
{
std::map<std::string, RangeCheckedVal<int,0,5> > myMap;
myMap[ "aa" ] = 5; // ok
myMap[ "bb" ] = 10; // throws an exception
}

Thank,
This is nice, but I think this way both "aa" and "bb" would have
same range. What I wanted, is somehow to overwrite assignment, and
check if "aa" then range is 0 to 5, if "bb" then range is 3 to 9
for example.


Question 2:

How do I prevent my map to be only 2 elements, "aa" and "bb", so
creation of new element "cc" would not be allowed.


Make the map const. To do this, you'd need to initialize the class on
declaration somehow, e.g.:

template<class K, class V>
class MapInitializer
{
typedef std::map<K,V> Map;
Map m_;
public:
operator Map() const { return m_; }

MapInitializer& Add( const K& k, const V& v )
{
m_[k] = v;
return *this;
}
};

const std::map<std::string,int> myMap
= MapInitializer<std::string, int>()
.Add( "aa", 9 )
.Add( "bb", 42 );

Of course, if the map is const, the [] operator won't work (outside the
initializer) since it inserts a key/value pair if one doesn't exist,
but std::map::find() is safer anyway.

Cheers! --M

I will need more time to exercise this.
 
M

mlimber

Haro said:
Question 1:

How do I create my own map, which would allow me to check during

MyMap["aa"] = 10;

that values for "aa" can be from 0 to 5, so the above assignment
would print error message.


Create a class that does range checking and automatically converts to
and from int, e.g. (untested code):

#include <map>
#include <string>
#include <exception>

template<typename T, T lower, T upper>
class RangeCheckedVal
{
T val_;

static T Validate( const T& val )
{
if( val < lower || val > upper )
{
throw std::range_error( "Value out of range" );
}
return val;
}

public:
RangeCheckedVal( const T& val = lower )
: val_( Validate(val) )
{}

operator T() const { return val_; }
};

int main()
{
std::map<std::string, RangeCheckedVal<int,0,5> > myMap;
myMap[ "aa" ] = 5; // ok
myMap[ "bb" ] = 10; // throws an exception
}

Thank,
This is nice, but I think this way both "aa" and "bb" would have
same range. What I wanted, is somehow to overwrite assignment, and
check if "aa" then range is 0 to 5, if "bb" then range is 3 to 9
for example.

Then you'll probably want to implement your own class that encapsulates
a map (or some other data structure).

Cheers! --M
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top