STL map compare function - can I pass a parameter?

Discussion in 'C++' started by Martoon, Apr 19, 2006.

  1. Martoon

    Martoon Guest

    I want to instantiate an STL map with my own compare function, and I
    want to pass a parameter to the compare function that will be stored
    and used for all comparisons in that map instance.

    As an example, let's say the map key is char* strings, and I want the
    comparison based on the nth character in the string. When the map is
    instantiated, I need to somehow specify n. So I might have something
    like this:

    class MyClass
    {
    public:
    void MyFunction(int i);

    private:
    class MyCompare
    {
    public:
    MyCompare() : m_iCharIndex(0) {}
    MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}

    bool operator()(const char* c1, const char* c2) const
    {
    return c1[m_iCharIndex] < c2[m_iCharIndex];
    }
    int m_iCharIndex;
    };
    };


    void MyClass::MyFunction(int i)
    {
    // this uses default constructor for MyCompare()
    std::map<const char*, float, MyCompare> myMap;

    // how do I use MyCompare(i) instead?
    }


    I can create a map with a char* key and MyCompare as the compare
    function. But what I want to do is somehow set the m_iCharIndex member
    of the MyCompare class for each map that I create (so I might have one
    map that keys on the 3rd character of the strings, another that keys on
    the 17th character, etc.).

    Is there any way that I can do something like this? I'm not actually
    trying to implement an nth character compare class. That's just a
    concrete example I came up with for illustration purposes. But I am
    trying to find a way to pass a parameter to a compare function for each
    map that I create. And that parameter will be stored and used in all
    comparisons for that map instance.

    Any help appreciated.
    Martoon, Apr 19, 2006
    #1
    1. Advertising

  2. Martoon wrote:
    > I want to instantiate an STL map with my own compare function, and I
    > want to pass a parameter to the compare function that will be stored
    > and used for all comparisons in that map instance.
    >
    > As an example, let's say the map key is char* strings, and I want the
    > comparison based on the nth character in the string. When the map is
    > instantiated, I need to somehow specify n. So I might have something
    > like this:
    >
    > class MyClass
    > {
    > public:
    > void MyFunction(int i);
    >
    > private:
    > class MyCompare
    > {
    > public:
    > MyCompare() : m_iCharIndex(0) {}
    > MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}


    You should probalby merge the two:

    MyCompare(int iCharIndex = 0) : m_iCharIndex(iCharIndex) {}

    >
    > bool operator()(const char* c1, const char* c2) const
    > {
    > return c1[m_iCharIndex] < c2[m_iCharIndex];
    > }
    > int m_iCharIndex;
    > };
    > };
    >
    >
    > void MyClass::MyFunction(int i)
    > {
    > // this uses default constructor for MyCompare()
    > std::map<const char*, float, MyCompare> myMap;
    >
    > // how do I use MyCompare(i) instead?


    RTFM about 'std::map's constructors.

    std::map<const char*, float, MyCompare> myMap(MyCompare(i));

    > }
    >
    > [..]


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Apr 19, 2006
    #2
    1. Advertising

  3. Martoon

    Martoon Guest

    Thanks! That's what I was looking for. I'm reading up on the map
    constructor.

    There's still one point I don't quite follow, though. I can do this:

    std::map<const char*, float, MyCompare> myMap(MyCompare(i));

    But if I then try to use myMap, it doesn't seem to recongize it as a
    map. For example,

    bool b = myMap.empty();

    yeilds a compiler error "left of '.empty' must have class/struct/union
    type". What am I missing here?
    Martoon, Apr 19, 2006
    #3
  4. Martoon wrote:
    > Thanks! That's what I was looking for. I'm reading up on the map
    > constructor.
    >
    > There's still one point I don't quite follow, though. I can do this:
    >
    > std::map<const char*, float, MyCompare> myMap(MyCompare(i));
    >
    > But if I then try to use myMap, it doesn't seem to recongize it as a
    > map. For example,
    >
    > bool b = myMap.empty();
    >
    > yeilds a compiler error "left of '.empty' must have class/struct/union
    > type". What am I missing here?


    My fault! You need the second set of parentheses, otherwise it's
    a function declaration:

    std::map<const char*, float, MyCompare> myMap((MyCompare(i)));

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Apr 19, 2006
    #4
  5. Martoon

    Martoon Guest

    Ahh, thanks! It's all good now.
    Martoon, Apr 19, 2006
    #5
  6. Martoon

    Kai-Uwe Bux Guest

    Martoon wrote:

    > I want to instantiate an STL map with my own compare function, and I
    > want to pass a parameter to the compare function that will be stored
    > and used for all comparisons in that map instance.
    >
    > As an example, let's say the map key is char* strings, and I want the
    > comparison based on the nth character in the string. When the map is
    > instantiated, I need to somehow specify n. So I might have something
    > like this:
    >
    > class MyClass
    > {
    > public:
    > void MyFunction(int i);
    >
    > private:
    > class MyCompare
    > {
    > public:
    > MyCompare() : m_iCharIndex(0) {}
    > MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}
    >
    > bool operator()(const char* c1, const char* c2) const
    > {
    > return c1[m_iCharIndex] < c2[m_iCharIndex];
    > }
    > int m_iCharIndex;
    > };
    > };

    [snip]

    You have received already advice on how to get this syntactically straight.
    However, the code above does no look sound: I have serious doubts that
    comparing strings based on their i-th character alone yields a strict weak
    ordering for the data types in your application. In other words: your
    comparison predicate could cause undefined behavior in std::map.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 19, 2006
    #6
  7. Martoon

    Mark P Guest

    Kai-Uwe Bux wrote:
    > Martoon wrote:
    >
    >> I want to instantiate an STL map with my own compare function, and I
    >> want to pass a parameter to the compare function that will be stored
    >> and used for all comparisons in that map instance.
    >>
    >> As an example, let's say the map key is char* strings, and I want the
    >> comparison based on the nth character in the string. When the map is
    >> instantiated, I need to somehow specify n. So I might have something
    >> like this:
    >>
    >> class MyClass
    >> {
    >> public:
    >> void MyFunction(int i);
    >>
    >> private:
    >> class MyCompare
    >> {
    >> public:
    >> MyCompare() : m_iCharIndex(0) {}
    >> MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}
    >>
    >> bool operator()(const char* c1, const char* c2) const
    >> {
    >> return c1[m_iCharIndex] < c2[m_iCharIndex];
    >> }
    >> int m_iCharIndex;
    >> };
    >> };

    > [snip]
    >
    > You have received already advice on how to get this syntactically straight.
    > However, the code above does no look sound: I have serious doubts that
    > comparing strings based on their i-th character alone yields a strict weak
    > ordering for the data types in your application.


    Why do you say so? Assuming that all strings do in fact have an i-th
    character, this looks like a valid strict weak ordering.

    On the other hand, since a map will not allow multiple keys which
    compare equal, it seems that this may not be a very useful structure,
    but then only the OP knows what he wants to do with this.

    Mark

    In other words: your
    > comparison predicate could cause undefined behavior in std::map.
    >
    >
    > Best
    >
    > Kai-Uwe Bux
    >
    Mark P, Apr 19, 2006
    #7
  8. Martoon

    Kai-Uwe Bux Guest

    Mark P wrote:

    > Kai-Uwe Bux wrote:
    >> Martoon wrote:
    >>
    >>> I want to instantiate an STL map with my own compare function, and I
    >>> want to pass a parameter to the compare function that will be stored
    >>> and used for all comparisons in that map instance.
    >>>
    >>> As an example, let's say the map key is char* strings, and I want the
    >>> comparison based on the nth character in the string. When the map is
    >>> instantiated, I need to somehow specify n. So I might have something
    >>> like this:
    >>>
    >>> class MyClass
    >>> {
    >>> public:
    >>> void MyFunction(int i);
    >>>
    >>> private:
    >>> class MyCompare
    >>> {
    >>> public:
    >>> MyCompare() : m_iCharIndex(0) {}
    >>> MyCompare(int iCharIndex) : m_iCharIndex(iCharIndex) {}
    >>>
    >>> bool operator()(const char* c1, const char* c2) const
    >>> {
    >>> return c1[m_iCharIndex] < c2[m_iCharIndex];
    >>> }
    >>> int m_iCharIndex;
    >>> };
    >>> };

    >> [snip]
    >>
    >> You have received already advice on how to get this syntactically
    >> straight. However, the code above does no look sound: I have serious
    >> doubts that comparing strings based on their i-th character alone yields
    >> a strict weak ordering for the data types in your application.

    >
    > Why do you say so? Assuming that all strings do in fact have an i-th
    > character, this looks like a valid strict weak ordering.


    That is why I said "serious doubts" instead of: it will not work.

    Also, from a standards point of view, the requirement is that the predicate
    defines a strict weak ordering on the *type* for the keys. No restriction
    is made that only the values actually used in the map have to be ordered.


    > On the other hand, since a map will not allow multiple keys which
    > compare equal, it seems that this may not be a very useful structure,
    > but then only the OP knows what he wants to do with this.


    True, and that is why my post was carefully worded:
    >> your comparison predicate could cause undefined behavior in std::map.

    ^^^^^

    In any case, I just wanted to alert the OP of a potential pitfall in his
    code. No claim on my part is made as to whether there will be trouble or
    not. All I claim is that the code look somewhat dangerous.


    Best

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 20, 2006
    #8
  9. Martoon

    Guest

    Kai-Uwe Bux wrote:
    > I have serious doubts that comparing strings based on their i-th
    > character alone yields a strict weak ordering for the data types
    > in your application.


    Any strict weak ordering of a domain Y is equivalent to a strict weak
    ordering of domain X, if there is a deterministic mapping y = f(x).

    In this case, the domain of strings Y is ordered by any strict weak
    ordering
    of optional<char> and the function optional<char> get_n(string s);

    HTH,
    Michiel Salters
    , Apr 20, 2006
    #9
  10. Martoon

    Kai-Uwe Bux Guest

    wrote:

    > Kai-Uwe Bux wrote:
    >> I have serious doubts that comparing strings based on their i-th
    >> character alone yields a strict weak ordering for the data types
    >> in your application.

    >
    > Any strict weak ordering of a domain Y is equivalent to a strict weak
    > ordering of domain X, if there is a deterministic mapping y = f(x).
    >
    > In this case, the domain of strings Y is ordered by any strict weak
    > ordering
    > of optional<char> and the function optional<char> get_n(string s);


    Oops, my bad. I confused it for a total ordering.


    Thanks

    Kai-Uwe Bux
    Kai-Uwe Bux, Apr 20, 2006
    #10
    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:
    496
    Markus Schoder
    Apr 16, 2006
  2. Replies:
    2
    Views:
    668
    Ivan Vecerina
    May 4, 2006
  3. NewToCPP

    key compare problem in stl map

    NewToCPP, Dec 13, 2006, in forum: C++
    Replies:
    10
    Views:
    3,870
    =?ISO-8859-15?Q?Juli=E1n?= Albo
    Dec 15, 2006
  4. S S
    Replies:
    5
    Views:
    1,132
    James Kanze
    Jun 24, 2008
  5. AzamSharp
    Replies:
    2
    Views:
    165
Loading...

Share This Page