STL map, compare function

Discussion in 'C++' started by S S, Jun 23, 2008.

  1. S S

    S S Guest

    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
     
    S S, Jun 23, 2008
    #1
    1. Advertising

  2. S S

    Kai-Uwe Bux Guest

    S S wrote:

    > 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
     
    Kai-Uwe Bux, Jun 23, 2008
    #2
    1. Advertising

  3. S S wrote:
    > 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.
     
    Juha Nieminen, Jun 23, 2008
    #3
  4. S S

    S S Guest

    On Jun 23, 7:19 pm, Kai-Uwe Bux <> wrote:
    > S S wrote:
    > > 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.


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

    >
    > > 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_.


    This wont help probably as I need to let mComp point differently
    depending on each 'abc' object.

    >
    > > 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


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

    > and right now you are about to compound it.
    >
    > Best
    >
    > Kai-Uwe Bux
     
    S S, Jun 23, 2008
    #4
  5. S S

    Kai-Uwe Bux Guest

    S S wrote:

    > On Jun 23, 7:19 pm, Kai-Uwe Bux <> wrote:
    >> S S wrote:
    >> > 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.

    >
    > 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.)

    >>
    >> > 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_.

    >
    > 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.


    >> > 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

    >
    > 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
     
    Kai-Uwe Bux, Jun 23, 2008
    #5
  6. S S

    James Kanze Guest

    On Jun 23, 3:27 pm, S S <> wrote:

    > 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
    std::less< key_type >, but of course, there's no point in it in
    that case.)

    > 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).

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jun 24, 2008
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    5
    Views:
    511
    Markus Schoder
    Apr 16, 2006
  2. Martoon
    Replies:
    9
    Views:
    827
    Kai-Uwe Bux
    Apr 20, 2006
  3. Replies:
    2
    Views:
    680
    Ivan Vecerina
    May 4, 2006
  4. NewToCPP

    key compare problem in stl map

    NewToCPP, Dec 13, 2006, in forum: C++
    Replies:
    10
    Views:
    3,904
    =?ISO-8859-15?Q?Juli=E1n?= Albo
    Dec 15, 2006
  5. nw
    Replies:
    5
    Views:
    395
    Permostat
    Mar 12, 2010
Loading...

Share This Page