STL map, compare function

S

S S

Hi

I have a requirement where I am declaring a map within a class.

class abc {
map <void*, void*> mMap; // I do not pass compare struct here.
....
};

Here I am not passing compare function, but I want to do it into the
constructor of class abc. Is it possible? Above void* could well be
char* and in that case user will initialize it with some char compare
function , but I don't know how to accomplish above task. Can I do
something like

abc::abc() : mMap(compare_string) {}

But above dosen't work !!

So I want to try something like function pointers, see the code below

bool comp_default(const void *a, const void *b) { return a < b; }
bool CharStringCompare(const void* a, const void* b) {return
strcmp((char*)a, (char*)b) < 0;}
struct compare_key_ {
bool operator()(const void* a, const void* b)
{
return (abc::*mComp)(a, b); // I know this is wrong as I am not
using object here
}
};

class abc {
friend struct compare_key_;
bool (abc::*mComp) (const void*, const void*) ;
map<void*, void*, compare_key_> mMap;
....
};

But above code is not the correct thing I am doing, I just wanted to
let you know the direction I am thinking? Can someone please help me
out.

Thanks
S
 
K

Kai-Uwe Bux

S said:
Hi

I have a requirement where I am declaring a map within a class.

class abc {
map <void*, void*> mMap; // I do not pass compare struct here.
...
};

Here I am not passing compare function, but I want to do it into the
constructor of class abc. Is it possible?

No. You have to specify the type of the comparison object beforehand.
Above void* could well be
char* and in that case user will initialize it with some char compare
function , but I don't know how to accomplish above task.

Sounds like a bad idea. But anyway, you can use tr1::function, somewhat
like so:

typedef tr1::function< bool(void*,void*) > void_ptr_compare;
map< void*, void*, void_ptr_compare > mMap;

Now, you can initialize mMap from anything that can be used to compare
void*.
Can I do something like

abc::abc() : mMap(compare_string) {}

But above dosen't work !!

Well, that would depend on many things (including the meaning of
compare_string).
So I want to try something like function pointers, see the code below

bool comp_default(const void *a, const void *b) { return a < b; }
bool CharStringCompare(const void* a, const void* b) {return
strcmp((char*)a, (char*)b) < 0;}
struct compare_key_ {
bool operator()(const void* a, const void* b)
{
return (abc::*mComp)(a, b); // I know this is wrong as I am not
using object here
}
};

Make the function pointer a member of compare_key_ and pass it upon
construction of compare_key_.
class abc {
friend struct compare_key_;
bool (abc::*mComp) (const void*, const void*) ;
map<void*, void*, compare_key_> mMap;
...
};

But above code is not the correct thing I am doing, I just wanted to
let you know the direction I am thinking? Can someone please help me
out.

You seem to be headed the wrong direction. What is the underlying problem
you are trying to solve. Very likely, the use of void* is already a mistake
and right now you are about to compound it.


Best

Kai-Uwe Bux
 
J

Juha Nieminen

S said:
map <void*, void*> mMap; // I do not pass compare struct here.

In C++, if you feel the need to use void* (except when dealing with
some C library), that's a good sign that you are doing something wrong.

I have programmed C++ as a hobby and professionally for about 10
years, and I have never needed to use "void*". (Well, I actually have a
few times, but only when dealing with some C libraries which required
them. That's an exception.)

Anyways, std::map requires that you give the comparator type as
template parameter if the default comparator doesn't suffice. There's no
way around that.
 
S

S S

No. You have to specify the type of the comparison object beforehand.

If you look for STL map's function, it says a constructor like,
map(const key_compare& k)
Not sure what it is for..
Sounds like a bad idea. But anyway,  you can use tr1::function, somewhat
like so:

  typedef tr1::function< bool(void*,void*) > void_ptr_compare;
  map< void*, void*, void_ptr_compare > mMap;

Now, you can initialize mMap from anything that can be used to compare
void*.




Well, that would depend on many things (including the meaning of
compare_string).



Make the function pointer a member of compare_key_ and pass it upon
construction of compare_key_.

This wont help probably as I need to let mComp point differently
depending on each 'abc' object.
You seem to be headed the wrong direction. What is the underlying problem
you are trying to solve. Very likely, the use of void* is already a mistake

I am trying to create a HashTable class (a hash implementation), here
I am using void*, it can store pointers / integers / char* /
anything....
 
K

Kai-Uwe Bux

S said:
If you look for STL map's function, it says a constructor like,
map(const key_compare& k)
Not sure what it is for..

It is for creating a map that uses k as the comparison predicate for keys.
However, that does not change the fact that the type key_compare has to be
specified beforehand. The map template takes up to four type parameters.
The third is the comparison predicate. So

map< key_type, mapped_type, key_compare >

is what you need. (The fourth argument would be the type for an allocator.)
This wont help probably as I need to let mComp point differently
depending on each 'abc' object.

And your point is? So, abc looks like so:

class abc {

map< void*, void*, compare_key_ > mMap;

public:

abc ( ..., bool(*comparison_ptr)(void*,void*) )
: mMap( compare_key_( comparison_ptr ) )
{}

...

};

However, tr1::function is more flexible than compare_key_ anyway.

I am trying to create a HashTable class (a hash implementation), here
I am using void*, it can store pointers / integers / char* /
anything....

No need for void*. Make your hash table a template.

template < typename KeyType, typename MappedType, typename HashFct >
class hash_table {
public:

hash_table( HashFct const & f = HashFct() );

void insert( KeyType const & key, MappedType const & value );#

...

};

It is to be used as follows:

hash_table< int, int, IntHash >


One could even go on and provide a default for HastFct that has
specializations for built-in types and other bells and whistles.



BTW: you could just use the hash table from the upcoming standard.
tr1::unordered_map might be more or less what you are looking for.




Best

Kai-Uwe Bux
 
J

James Kanze

I have a requirement where I am declaring a map within a class.
class abc {
map <void*, void*> mMap; // I do not pass compare struct here.
...
};
Here I am not passing compare function, but I want to do it
into the constructor of class abc.

There are two issues: the type of the comparator, and its
"value". The type becomes part of the type of the map, and must
be specified when you declare the map. (The map itself holds an
instance of this type, so the compiler must know its size.) The
value can be specified when you initialize the object, in this
case, in the initializer list of abc::abc. (It cannot be
changed later, except with swap, for obvious reasons.)

By default, the *type* of the comparator is std::less<Key>.
Since all instances of this class have the same behavior,
there's never any point of setting it to a particular value in
the constructor, but this is not necessarily true for other
comparators. If you declare:

map< void*, void*, bool (*)( void*, void* ) > mMap ;

for example, you almost certainly want to pass an actual
instance of the comparator to the constructor. (The default
value here is a null pointer, which isn't going to work too
well.)
Is it possible? Above void* could well be char* and in that
case user will initialize it with some char compare function ,
but I don't know how to accomplish above task. Can I do
something like
abc::abc() : mMap(compare_string) {}
But above dosen't work !!

It does if you declare mMap so that it takes a comparator of
type compare_string. (Or if compare_string has the type
but of course said:
So I want to try something like function pointers, see the
code below
bool comp_default(const void *a, const void *b) { return a < b; }
bool CharStringCompare(const void* a, const void* b) {return
strcmp((char*)a, (char*)b) < 0;}
struct compare_key_ {
bool operator()(const void* a, const void* b)
{
return (abc::*mComp)(a, b); // I know this is wrong as I am not
using object here
}
};

You don't need the structure.
class abc {
friend struct compare_key_;
bool (abc::*mComp) (const void*, const void*) ;
map<void*, void*, compare_key_> mMap;

Why not
std::map< void*, void*, bool (*)( void const*, void const* ) >
mMap ;
initialized with:

abc::abc()
: mMap( &CharStringCompare )
...
...

But above code is not the correct thing I am doing, I just
wanted to let you know the direction I am thinking? Can
someone please help me out.

Well, I'm very suspicious of your use of void* to begin with,
and I think you probably have to think about const correctness a
bit more as well. But there's no problem of having a comparator
which does something different depending on its state; a pointer
to function, for example (which will do something different
depending on which function it points to).
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top