std::map replacement

  • Thread starter Christopher Benson-Manica
  • Start date
C

Christopher Benson-Manica

If you liked the functionality of std::map, but found that you
couldn't trust your implementation to handle nonstandard data
structures, how would you code a wrapper? I've produced the
following:

#include <map>

template < class keytype, class recordtype >
class pseudomap
{
private:
map< keytype, unsigned int > maptable;
CustomList<recordtype> recordlist; // custom array-like class
// with methods including
// those used below

public:
void clear() {maptable.clear();recordlist.Clear();}

recordtype& operator[] ( const keytype& key )
{
if( maptable.count(key) ) {
return( *recordlist[maptable[key]] );
}
recordlist.Add( new recordtype() );
maptable[key]=recordlist.Count-1;
return( *recordlist[maptable[key]] );
}
};

I get the feeling that there is a lot to criticize about the code
above (although it seems to work just fine) - so I'm listening :)
Needless to say not all map functionality is included - but it's good
enough for my current needs...
 
A

Andre Kostur

If you liked the functionality of std::map, but found that you
couldn't trust your implementation to handle nonstandard data
structures, how would you code a wrapper? I've produced the
following:

What do you call "nonstandard data structures"?
#include <map>

template < class keytype, class recordtype >
class pseudomap
{
private:
map< keytype, unsigned int > maptable;
CustomList<recordtype> recordlist; // custom array-like class
// with methods including
// those used below

public:
void clear() {maptable.clear();recordlist.Clear();}

recordtype& operator[] ( const keytype& key )
{
if( maptable.count(key) ) {
return( *recordlist[maptable[key]] );
}
recordlist.Add( new recordtype() );
maptable[key]=recordlist.Count-1;
return( *recordlist[maptable[key]] );
}
};

I get the feeling that there is a lot to criticize about the code
above (although it seems to work just fine) - so I'm listening :)
Needless to say not all map functionality is included - but it's good
enough for my current needs...

How can we tell? You haven't stated what exactly you're trying to
accomplish!
 
M

Michiel Salters

Christopher Benson-Manica said:
If you liked the functionality of std::map, but found that you
couldn't trust your implementation to handle nonstandard data
structures, how would you code a wrapper?

By wrapping the non-standard data or implementing a proper
std::less<non_standard_data>.

Regards,
Michiel Salters
 
C

Christopher Benson-Manica

Michiel Salters said:
By wrapping the non-standard data or implementing a proper
std::less<non_standard_data>.

Well, the key was an unsigned int (the user-defined data was the
value), so I don't think the comparison function was the problem.
 
C

Christopher Benson-Manica

Andre Kostur said:
How can we tell? You haven't stated what exactly you're trying to
accomplish!

I thought I did - to create a data structure that acts like a map but
uses a map with only simple data types as the values. As I stated,
when using a class I defined as the second map template parameter,
things broke, and as far as I can tell it isn't my fault...
 
K

Karl Heinz Buchegger

Christopher said:
I thought I did - to create a data structure that acts like a map but
uses a map with only simple data types as the values. As I stated,
when using a class I defined as the second map template parameter,
things broke, and as far as I can tell it isn't my fault...

Show your class.
In almost all cases it *is* your fault.
 
C

Christopher Benson-Manica

Karl Heinz Buchegger said:
Show your class.
In almost all cases it *is* your fault.

Verbatim, with some names changed:

struct
MyClass {
private:
CustomClassA e;

public:
bool Valid;

_TDate Start;
_TDate End;
uint blockMTD;
uint blockYTD;
uint creditMTD;

bool HasNextPeriod;
_TDate nbStart;
_TDate nbEnd;
uint nbBlock;
uint nbCredit;

CustomClassB Exceptions; // list of CustomClassA's
void AddException( uint id, uint date, uint time ) {Exceptions.AddException(id,date,time);}
void AddException( const char *str ) {e.FromString(str);Exceptions.Add(e);}

EmployeeEvalInfo() {Valid=false;HasNextPeriod=false;Start=0;End=0;blockMTD=0;blockYTD=0;creditMTD=0;nbStart=0;nbEnd=0;nbBlock=0;nbCredit=0;}
};

Unless the implementations of CustomClassA and CustomClassB matter, I
don't see what the problem can be...
 
D

Derek

Christopher said:
If you liked the functionality of std::map, but found
that you couldn't trust your implementation to handle
nonstandard data structures, how would you code a
wrapper?

I'm not clear on what you mean by "nonstandard data
structures" and why you can't just insert your objects
into a std::map directly.

Are you getting compiler errors? Are you seeing
unexpected results at runtime?
 
C

Christopher Benson-Manica

Derek said:
Are you getting compiler errors? Are you seeing
unexpected results at runtime?

Unexpected results at runtime, and the debugger points at the std::map
implementation...
 
J

Jeff Flinn

Christopher Benson-Manica said:
Verbatim, with some names changed:

struct
MyClass {
private:
CustomClassA e;

public:
bool Valid;

_TDate Start;
_TDate End;
uint blockMTD;
uint blockYTD;
uint creditMTD;

bool HasNextPeriod;
_TDate nbStart;
_TDate nbEnd;
uint nbBlock;
uint nbCredit;

CustomClassB Exceptions; // list of CustomClassA's
void AddException( uint id, uint date, uint time ) {Exceptions.AddException(id,date,time);}
void AddException( const char *str ) {e.FromString(str);Exceptions.Add(e);}
{Valid=false;HasNextPeriod=false;Start=0;End=0;blockMTD=0;blockYTD=0;creditM
TD=0;nbStart=0;nbEnd=0;nbBlock=0;nbCredit=0;}
};

Unless the implementations of CustomClassA and CustomClassB matter, I
don't see what the problem can be...

I'm sure they do matter! All of your classes used here must be default
constructible, and copyable/assignable. If that is not possible define your
map as std::map< key, boost::shard_ptr<Myclass> >

Jeff F
 
C

Christopher Benson-Manica

Jeff Flinn said:
I'm sure they do matter! All of your classes used here must be default
constructible, and copyable/assignable. If that is not possible define your
map as std::map< key, boost::shard_ptr<Myclass> >

Well, I can't use boost, and I can't change how these classes are
implemented, so I guess I'll stick with what I posted originally.
 
D

Derek

Christopher said:
Unexpected results at runtime, and the debugger points at
the std::map implementation...

Unless you are using an ancient or highly broken standard
library, I doubt it's the std::map implementation.

More likely that your "nonstandard" value class doesn't
implement correct copy semantics or contains some other bug.
 
D

Derek

Christopher said:
Well, I can't use boost, and I can't change how these
classes are implemented, so I guess I'll stick with what
I posted originally.

Why can't you use boost? Another possibility is to
use raw pointers and manage lifetime yourself, eg,
std::map<key, MyClass*>.

If the problem is that if your classes don't use correct
copy/assignment semantics, your wrapper may be very
fragile. It may work now, but it may fail completely on
another platform or stop working when you make what seems
like an unrelated change. Best to get to the root cause
of the problem.
 
C

Christopher Benson-Manica

Derek said:
Why can't you use boost?

It isn't my decision to make.
Another possibility is to
use raw pointers and manage lifetime yourself, eg,
std::map<key, MyClass*>.

I suppose, but it'd be a hassle.
If the problem is that if your classes don't use correct
copy/assignment semantics, your wrapper may be very
fragile.

Well, if it's fragile, it's because the custom classes are fragile; I
think map< int, int > is pretty stable.
 
C

Christopher Benson-Manica

Derek said:
Unless you are using an ancient or highly broken standard
library, I doubt it's the std::map implementation.

It's Borland 4, and I've found several instances where it's either
flat broken or breaks when our custom libraries are linked in.
More likely that your "nonstandard" value class doesn't
implement correct copy semantics or contains some other bug.

Possibly :)
 
J

Jeff Flinn

Christopher Benson-Manica said:
It isn't my decision to make.

Just curious as to the reason boost isn't allowed?
I suppose, but it'd be a hassle.

You'd be better off writing a wrapper for MyClass with appropriate
default/copy constructors than re-implementing a custom map.

Your already dealing with pointers in your pseudomap class, are you not?
It's difficult to comment on your code since much of the implementation
appears to be in CustomList<recordtype> which you didn't supply. But, I
don't understand why you even have the CustomList? You could:


Untested code follows:

template < class keytype, class recordtype >
class SeverelyLimitedMap
{
private:
typedef std::map< keytype, recordtype* > tPtrs;

tPtr mPtrs;

static void DeletePtr( typename tPtrs::value_type& aPair )
{
delete aPair.second;
}

public:
void clear()
{
std::for_each( mPtrs.begin(), mPtrs.end(), DeletePtr );

mPtrs.clear();
}

recordtype& operator[] ( const keytype& key )
{
tPtrs::iterator lItr = mPtrs.find( key );

if( lItr != mPtrs.end() )
{
return *lItr;
}
else
{
return *mPtrs.insert( tPtrs::value_type( key, new
recordtype ) ).first;
}
}
};


Jeff F
 
D

Default User

Derek said:
Why can't you use boost? Another possibility is to
use raw pointers and manage lifetime yourself, eg,
std::map<key, MyClass*>.


I've ranted about this before. Boost is not a part of standard C++. It
is a third-party library at this time. For those of us that work in a
controlled environment (you know like that make your planes fly and
stuff?) we can't willy-nilly throw in code that's not been approved.

It's fine for writing your non-security conscious programs, but for
others you'd have to get the appropriate people to review and pass on
the Boost library.



Brian Rodenborn
 
C

Christopher Benson-Manica

Jeff Flinn said:
Just curious as to the reason boost isn't allowed?

I'm still trying to convince my boss that the STL is a Good Thing
(tm), with only limited success. He certainly wouldn't trust boost :)
You'd be better off writing a wrapper for MyClass with appropriate
default/copy constructors than re-implementing a custom map.

It sounds like a good exercise. I'd try that, except that I don't
know enough about MyClass' implementation to do it... (among other
things, I'm not positive that it manages its memory with malloc,
although I think it does).
Your already dealing with pointers in your pseudomap class, are you not?
It's difficult to comment on your code since much of the implementation
appears to be in CustomList<recordtype> which you didn't supply. But, I
don't understand why you even have the CustomList? You could:

Well, using the CustomList is a nod to existing code :)
Untested code follows:

I've got to do some actual work here, but I'll take a look at that
sometime - thanks.
 
D

Derek

Why can't you use boost?
I've ranted about this before. Boost is not a part
of standard C++. It is a third-party library at this
time. For those of us that work in a controlled
environment (you know like that make your planes fly and
stuff?) we can't willy-nilly throw in code that's not
been approved.

It's fine for writing your non-security conscious
programs, but for others you'd have to get the
appropriate people to review and pass on the Boost
library.

I share your concerns, but the only Boost component
mentioned in this thread was boost::shared_ptr. Even
though my employer does not allow Boost in general, we
do use shared_ptr because (a) it's safer than the smart
pointers we wrote in house, (b) it's very portable, and
(c) it's very likely to be in the next standard.

Of course if your application is so critical that it "makes
planes fly and stuff," then Boost may not be appropriate.
In fact, I'm not sure C++ is entirely appropriate in such
circumstances, unless used as a limited subset of the full
language. I'd rather not think what my 747 autopilot will
do when 'new' throws std::bad_alloc. ;)
 
P

Pete Becker

Derek said:
I'd rather not think what my 747 autopilot will
do when 'new' throws std::bad_alloc. ;)

If you don't trust the author of the software to handle bad_alloc
correctly why do you trust him to handle a null pointer correctly?
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top