map key classes

This is a discussion on map key classes within the C++ Programming forums, part of the General Programming Boards category; i'm having an odd error using a class as a key in std::map. the class contains 2 64b ints and ...

  1. #1
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839

    map key classes

    i'm having an odd error using a class as a key in std::map.

    the class contains 2 64b ints and 1 enum entry. i've implemented the < and == operators, but when i call insert on the map, nothing happens after the first entry. no errors, no changes, it just doesn't do anything!

    pseudocode:

    Code:
    class keytype
    {
      private:
        _uint64 id;
        someEnum enumVal;
        _uint64 address;
      public:
        keytype(_uint64 _id,someEnum _enumVal,_uint64 _address):
          id(_id),
          enumVal(_enumVal),
          address(_address)
        {
        }
        bool operator ==(const DispatchInfo& di)const
        {
          return id == di.id && enumVal == di.enumVal && address == di.address;
        }
        bool operator <(const DispatchInfo& di)const
        {            
          return id <di.id && enumVal < di.enumVal && address < di.address;
        }
    };
    
    class valtype
    {
    };
    
    
    class someOtherClass
    {
      std::map<keytype,valtype>problematicMap;
      public:
      template<class C>inline void registrationMethod(C& cinst,_uint64 id,someEnum enumVal)
      {
        problematicMap[keytype(id,enumVal,(_uint64)&cinst)]=new valtype()
      }
    };

    any ideas? i have never had this problem before :\

    TIA
    Last edited by m37h0d; 09-28-2009 at 10:50 AM.

  2. #2
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    aah apparently i needed to just order based off of address. i didn't particularly care about the ordering, but apparently it required some thought.

    can anyone shed some light on the mechanics involved that one should be aware of in situations like this?

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Where does this bigint2 come from?

    It is possible that your operator< don't define strict weak ordering (that means both a < b and b < a can be true at the same time).

    Addresses might be comparable, but how exactly are you planning to find the exact item that you need?
    Last edited by anon; 09-28-2009 at 10:43 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    Quote Originally Posted by anon View Post
    Where does this bigint2 come from?

    It is possible that your operator< don't define strict weak ordering (that means both a < b and b < a can be true at the same time).

    Addresses might be comparable, but how exactly are you planning to find the exact item that you need?

    Quote Originally Posted by anon View Post
    Where does this bigint2 come from?
    sorry, that was supposed to be "id". F&R fail.

    Quote Originally Posted by anon View Post
    It is possible that your operator< don't define strict weak ordering (that means both a < b and b < a can be true at the same time).
    yes, that would appear to be the problem.

    Quote Originally Posted by anon View Post
    Addresses might be comparable, but how exactly are you planning to find the exact item that you need?
    well, apparently that requires a little more thought. i'm not sure at this point. any ideas or pointers on defining the requirements would be much appreciated.


    i need to be able to register multiple methods from a single class instance, but the id will be unique for each method.

  5. #5
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    yes, predictably this fails if i try to register multiple methods.

    the most straightforward solution i can think of is a map of maps.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
        bool operator <(const DispatchInfo& di)const
        {            
          return id <di.id && enumVal < di.enumVal && address < di.address;
        }
    This is what the map uses (it doesn't use operator==). If a < b == false and b < a == false then the items are equivalent. Given your operator< lots of objects are going to be treated as equivalent (and as the map stores only one of multiple equivalent items, you are going to see only one added).

    The comparison function needs to be more complicated. For two values to compare it should look something like:

    Code:
    if (a.first < b.first) {
        return true;
    }
    else if (!(b.first < a.first)) { //i.e a.first == b.first
        return a.second < b.second;
    }
    return false;
    And here's just for fun, some template metaprogramming that produces a comparator to compare using four members.

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <iterator>
    #include <cstdlib>
    
    template <class F1, class F2>
    class MultiCompareT
    {
        F1 fun1;
        F2 fun2;
    public:
        MultiCompareT(F1 f1, F2 f2): fun1(f1), fun2(f2) {}
        template <class T>
        bool operator() (const T& a, const T& b)
        {
            return fun1(a, b) || (!fun1(b, a) && fun2(a, b));
        }
        template <class F3>
        MultiCompareT<F1, MultiCompareT<F2, MultiCompareT<F3, void> > > then(F3 fun3)
        {
            return MultiCompareT<F1, MultiCompareT<F2, MultiCompareT<F3, void> > >(
                fun1,
                MultiCompareT<F2, MultiCompareT<F3, void> >(
                    fun2,
                    MultiCompareT<F3, void>(fun3)
                )
            );
        }
    };
    
    template <class F>
    class MultiCompareT<F, void>
    {
        F fun;
    public:
        MultiCompareT(F f): fun(f) {}
        template <class T>
        bool operator() (const T& a, const T& b)
        {
            return fun(a, b);
        }
        template <class F2>
        MultiCompareT<F, MultiCompareT<F2, void> > then(F2 fun2)
        {
            return MultiCompareT<F, MultiCompareT<F2, void> >(fun, MultiCompareT<F2, void>(fun2));
        }
    };
    
    template <class F>
    MultiCompareT<F, void> MultiCompare(F fun)
    {
        return MultiCompareT<F, void>(fun);
    };
    
    template <class O, class T>
    class CompareMemberT
    {
        T O::*ptr;
    public:
        CompareMemberT(T O::*ptr): ptr(ptr) {}
        bool operator() (const O& a, const O& b) const
        {
            return (a.*ptr) < (b.*ptr);
        }
    };
    
    template <class O, class T>
    CompareMemberT<O, T> CompareMember(T O::*ptr)
    {
        return CompareMemberT<O, T>(ptr);
    };
    
    struct Test
    {
        unsigned u;
        int i;
        char c;
        bool b;
    };
    
    std::ostream& operator<< (std::ostream& os, const Test& t)
    {
        return os << "(" << t.u << ", " << t.i << ", " << t.c << ", " << t.b << ")";
    }
    
    int main()
    {
        std::vector<Test> vec;
        for (int i = 0; i != 44; ++i) {
            Test t = { rand() % 8, rand() % 8, rand() % 4 + 'a', rand() % 2 };
            vec.push_back(t);
        }
        std::sort(vec.begin(), vec.end(),
            MultiCompare(CompareMember(&Test::u))
                .then(CompareMember(&Test::i))
                .then(CompareMember(&Test::c))
                .then(CompareMember(&Test::b))
            );
        std::cout << std::boolalpha << '\n';
        std::copy(vec.begin(), vec.end(), std::ostream_iterator<Test>(std::cout, "\n"));
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    22,269
    Quote Originally Posted by anon
    The comparison function needs to be more complicated. For two values to compare it should look something like:
    Or more concisely while also assuming that operator== is not available:
    Code:
    return a.first < b.first || !(b.first < a.first) && a.second < b.second;
    which incidentally I note is the form used in your template metaprogramming example.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Yes, I thought I'd write it out in a longer form, so the logic might be easier to follow.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    3735928559
    Join Date
    Mar 2008
    Location
    RTP
    Posts
    839
    thanks for the code anon. i trust it will be illuminating once i have a chance to study it more.

    i think my problem is that i am trying to encapsulate two many-to-one relationships in a single many-to-one.

    breaking the lookup into two parts is more natural for my purposes and greatly simplifies the implementation. funny how those two things seem to go together eh?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Finding a key in a map returns true always
    By Zach_the_Lizard in forum C++ Programming
    Replies: 2
    Last Post: 09-10-2009, 06:33 PM
  2. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 07:02 AM
  3. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 09:32 AM
  4. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 08:26 PM
  5. include question
    By Wanted420 in forum C++ Programming
    Replies: 8
    Last Post: 10-17-2003, 04:49 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21