Haro Panosyan wrote:
Quote:
#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, intMyMap;
>
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
}
Quote:
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,VMap;
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,intmyMap
= 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