Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Invalid comparator for STL map

Invalid comparator for STL map

Scheduled Pinned Locked Moved C / C++ / MFC
c++
13 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F ForNow

    Hi I am getting invalid comparator for the following code and I just dont get it at the very end there is always a path to return

    struct usingrange
    {
    ESDID esdid;
    int start;
    int end;

    usingrange() { start = 0; end = 0; return; }
    

    bool operator<(const usingrange x) const {
    if (esdid <= x.esdid) return esdid <= x.esdid;
    if (start <= x.start) return start <= x.start; if (end <= x.end) return end <= x.end;
    else
    return FALSE;

    D Offline
    D Offline
    Daniel Pfeffer
    wrote on last edited by
    #2

    Shouldn't you be passing usingrange as a reference to your comparison function?

    bool operator<(const usingrange**&** x) const

    Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.

    F 2 Replies Last reply
    0
    • D Daniel Pfeffer

      Shouldn't you be passing usingrange as a reference to your comparison function?

      bool operator<(const usingrange**&** x) const

      Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.

      F Offline
      F Offline
      ForNow
      wrote on last edited by
      #3

      It’s a member of key type

      1 Reply Last reply
      0
      • D Daniel Pfeffer

        Shouldn't you be passing usingrange as a reference to your comparison function?

        bool operator<(const usingrange**&** x) const

        Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.

        F Offline
        F Offline
        ForNow
        wrote on last edited by
        #4

        this is were I am getting the exception at the line with STL_VERIFY

        // FUNCTION TEMPLATE _Debug_lt_pred
        template , _Remove_cvref_t<_Ty2>>, int> = 0>
        constexpr bool _Debug_lt_pred(_Pr&& _Pred, _Ty1&& _Left, _Ty2&& _Right) noexcept(
        noexcept(_Pred(_Left, _Right)) && noexcept(_Pred(_Right, _Left))) {
        // test if _Pred(_Left, _Right) and _Pred is strict weak ordering, when the arguments are the cv-same-type
        const auto _Result = static_cast(_Pred(_Left, _Right));
        if (_Result) {
        _STL_VERIFY(!_Pred(_Right, _Left), "invalid comparator");

        this is my code

        struct usingrange
        {
        ESDID esdid;
        int start;
        int end;

        usingrange() { start = 0; end = 0; return; }
        

        bool operator<(const usingrange& x) const {
        if (esdid < x.esdid)
        return esdid < x.esdid;
        if (start < x.start)
        return start < x.start;
        if (end < x.end) return end < x.end;
        else
        return x.end < end;

        when I change mt code to

        bool operator<(const usingrange& x) const {

         return start < x.start;
        

        }

        everything works I dont get it the operator is excepting a bool retrun code true or false in either I retrun that

        G 1 Reply Last reply
        0
        • F ForNow

          this is were I am getting the exception at the line with STL_VERIFY

          // FUNCTION TEMPLATE _Debug_lt_pred
          template , _Remove_cvref_t<_Ty2>>, int> = 0>
          constexpr bool _Debug_lt_pred(_Pr&& _Pred, _Ty1&& _Left, _Ty2&& _Right) noexcept(
          noexcept(_Pred(_Left, _Right)) && noexcept(_Pred(_Right, _Left))) {
          // test if _Pred(_Left, _Right) and _Pred is strict weak ordering, when the arguments are the cv-same-type
          const auto _Result = static_cast(_Pred(_Left, _Right));
          if (_Result) {
          _STL_VERIFY(!_Pred(_Right, _Left), "invalid comparator");

          this is my code

          struct usingrange
          {
          ESDID esdid;
          int start;
          int end;

          usingrange() { start = 0; end = 0; return; }
          

          bool operator<(const usingrange& x) const {
          if (esdid < x.esdid)
          return esdid < x.esdid;
          if (start < x.start)
          return start < x.start;
          if (end < x.end) return end < x.end;
          else
          return x.end < end;

          when I change mt code to

          bool operator<(const usingrange& x) const {

           return start < x.start;
          

          }

          everything works I dont get it the operator is excepting a bool retrun code true or false in either I retrun that

          G Offline
          G Offline
          Graham Breach
          wrote on last edited by
          #5

          Does your ESDID class have an operator<() function? If not, add one.

          F 2 Replies Last reply
          0
          • G Graham Breach

            Does your ESDID class have an operator<() function? If not, add one.

            F Offline
            F Offline
            ForNow
            wrote on last edited by
            #6

            Thank you so much actually everything is a structure I am a very open :) person I got to tell you something you C++ guys a geniuses

            1 Reply Last reply
            0
            • G Graham Breach

              Does your ESDID class have an operator<() function? If not, add one.

              F Offline
              F Offline
              ForNow
              wrote on last edited by
              #7

              still getting the exception if the key to the map is a structure consisting of a char[4] and 2 int how would I set < operator the only way I got it to work was by return int1 < x.int1 what would like to do is concatenate all of them in 12 bytes and compare 12 bytes against 12 bytes thanks

              F 2 Replies Last reply
              0
              • F ForNow

                still getting the exception if the key to the map is a structure consisting of a char[4] and 2 int how would I set < operator the only way I got it to work was by return int1 < x.int1 what would like to do is concatenate all of them in 12 bytes and compare 12 bytes against 12 bytes thanks

                F Offline
                F Offline
                ForNow
                wrote on last edited by
                #8

                Since my the total of my data was 12 bytes I was lucky there happened to be a data type 16 bytes long double just filled first 4 bytes with zeros and here is the code

                struct usingrange
                {
                ESDID esdid;
                int start;
                int end;

                usingrange() { start = 0; end = 0; return; }
                

                bool operator<(const usingrange& x) const {
                union
                {
                long double a;
                char str1[16];
                }c;
                union
                {
                long double b;
                char str2[16];
                }d;

                  ::memset(&c.str1, 0x00, 16);
                  ::memset(&d.str2, 0x00, 16);
                  ::memcpy(&c.str1\[4\], &esdid, 4);
                  ::memcpy(&c.str1\[8\],&start,4);
                  ::memcpy(&c.str1\[12\], &end, 4);
                  ::memcpy(&d.str2\[4\], &x.esdid, 4);
                  ::memcpy(&d.str2\[8\], &x.start, 4);
                  ::memcpy(&d.str2\[12\], &x.end, 4);
                
                  return c.a < d.b;
                
                //	  return usingrange  < x;
                //	  if (start < x.start) 
                 //   return start < x.start;
                

                // return x.end < end;

                }

                };

                1 Reply Last reply
                0
                • F ForNow

                  still getting the exception if the key to the map is a structure consisting of a char[4] and 2 int how would I set < operator the only way I got it to work was by return int1 < x.int1 what would like to do is concatenate all of them in 12 bytes and compare 12 bytes against 12 bytes thanks

                  F Offline
                  F Offline
                  ForNow
                  wrote on last edited by
                  #9

                  Since my data was 12 bytes long I was lucky there happened to be a data type 16 bytes long a "long double" I just filled the first 4 bytes with zeros and

                  ;
                  struct usingrange
                  {
                  ESDID esdid;
                  int start;
                  int end;

                  usingrange() { start = 0; end = 0; return; }
                  

                  bool operator<(const usingrange& x) const {
                  union
                  {
                  long double a;
                  char str1[16];
                  }c;
                  union
                  {
                  long double b;
                  char str2[16];
                  }d;

                    ::memset(&c.str1, 0x00, 16);
                    ::memset(&d.str2, 0x00, 16);
                    ::memcpy(&c.str1\[4\], &esdid, 4);
                    ::memcpy(&c.str1\[8\],&start,4);
                    ::memcpy(&c.str1\[12\], &end, 4);
                    ::memcpy(&d.str2\[4\], &x.esdid, 4);
                    ::memcpy(&d.str2\[8\], &x.start, 4);
                    ::memcpy(&d.str2\[12\], &x.end, 4);
                  
                    return c.a < d.b;
                  
                  //	  return usingrange  < x;
                  //	  if (start < x.start) 
                   //   return start < x.start;
                  

                  // return x.end < end;

                  }

                  };

                  K G 2 Replies Last reply
                  0
                  • F ForNow

                    Since my data was 12 bytes long I was lucky there happened to be a data type 16 bytes long a "long double" I just filled the first 4 bytes with zeros and

                    ;
                    struct usingrange
                    {
                    ESDID esdid;
                    int start;
                    int end;

                    usingrange() { start = 0; end = 0; return; }
                    

                    bool operator<(const usingrange& x) const {
                    union
                    {
                    long double a;
                    char str1[16];
                    }c;
                    union
                    {
                    long double b;
                    char str2[16];
                    }d;

                      ::memset(&c.str1, 0x00, 16);
                      ::memset(&d.str2, 0x00, 16);
                      ::memcpy(&c.str1\[4\], &esdid, 4);
                      ::memcpy(&c.str1\[8\],&start,4);
                      ::memcpy(&c.str1\[12\], &end, 4);
                      ::memcpy(&d.str2\[4\], &x.esdid, 4);
                      ::memcpy(&d.str2\[8\], &x.start, 4);
                      ::memcpy(&d.str2\[12\], &x.end, 4);
                    
                      return c.a < d.b;
                    
                    //	  return usingrange  < x;
                    //	  if (start < x.start) 
                     //   return start < x.start;
                    

                    // return x.end < end;

                    }

                    };

                    K Offline
                    K Offline
                    k5054
                    wrote on last edited by
                    #10

                    That has a couple of issues. Firstly, you are invoking undefined behavior: [Union declaration - cppreference.com](https://en.cppreference.com/w/cpp/language/union#:~:text=It is undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement%2C as a non-standard language extension%2C the ability to read inactive members of a union.) Secondly, you're expecting that the bit patterns of 2 doubles can be compared. This may not be the case, as you may a NaN this way, and then any comparison will return false:

                    [k5054@localhost tmp]$ cat example.c
                    #include

                    int main()
                    {
                    double d = 0.0 / 0.0; // produces NaN
                    printf("1.0 < d = %d\n", 1.0 < d);
                    printf("d < 1.0 = %d\n", d < 1.0);
                    printf("d == d = %d\n", d == d);
                    }
                    [k5054@localhost tmp]$ gcc example.c -o example
                    [k5054@localhost tmp]$ ./example
                    1.0 < d = 0
                    d < 1.0 = 0
                    d == d = 0
                    [k5054@localhost tmp]$

                    As we can see in the above code, NaN compared to anything, even itself returns false. If all you want to do is compare bits, you might as well just go ahead and use memcmp()

                    *#35;include
                    struct usingrange {
                    ESDID esdid;
                    int start;
                    int end;
                    // ... other stuff ...
                    bool operator<(const usingrange& x)const {
                    return ::memcmp(this, &x, sizeof(*this)
                    }
                    };

                    This relies on the fact that the sizeof a struct or a class is the size of its individual members. This only becomes tricky if your struct/class includes STL or other objects like std::string or std::vector.

                    Keep Calm and Carry On

                    F 1 Reply Last reply
                    0
                    • K k5054

                      That has a couple of issues. Firstly, you are invoking undefined behavior: [Union declaration - cppreference.com](https://en.cppreference.com/w/cpp/language/union#:~:text=It is undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement%2C as a non-standard language extension%2C the ability to read inactive members of a union.) Secondly, you're expecting that the bit patterns of 2 doubles can be compared. This may not be the case, as you may a NaN this way, and then any comparison will return false:

                      [k5054@localhost tmp]$ cat example.c
                      #include

                      int main()
                      {
                      double d = 0.0 / 0.0; // produces NaN
                      printf("1.0 < d = %d\n", 1.0 < d);
                      printf("d < 1.0 = %d\n", d < 1.0);
                      printf("d == d = %d\n", d == d);
                      }
                      [k5054@localhost tmp]$ gcc example.c -o example
                      [k5054@localhost tmp]$ ./example
                      1.0 < d = 0
                      d < 1.0 = 0
                      d == d = 0
                      [k5054@localhost tmp]$

                      As we can see in the above code, NaN compared to anything, even itself returns false. If all you want to do is compare bits, you might as well just go ahead and use memcmp()

                      *#35;include
                      struct usingrange {
                      ESDID esdid;
                      int start;
                      int end;
                      // ... other stuff ...
                      bool operator<(const usingrange& x)const {
                      return ::memcmp(this, &x, sizeof(*this)
                      }
                      };

                      This relies on the fact that the sizeof a struct or a class is the size of its individual members. This only becomes tricky if your struct/class includes STL or other objects like std::string or std::vector.

                      Keep Calm and Carry On

                      F Offline
                      F Offline
                      ForNow
                      wrote on last edited by
                      #11

                      The return using memcmp as operands will get an exception in order to get around this I need to to have to have the syntax return operand1 < operand2 truthfully the order of the items is not that important as long as I am able to retrieve the data by key thanks

                      1 Reply Last reply
                      0
                      • F ForNow

                        Since my data was 12 bytes long I was lucky there happened to be a data type 16 bytes long a "long double" I just filled the first 4 bytes with zeros and

                        ;
                        struct usingrange
                        {
                        ESDID esdid;
                        int start;
                        int end;

                        usingrange() { start = 0; end = 0; return; }
                        

                        bool operator<(const usingrange& x) const {
                        union
                        {
                        long double a;
                        char str1[16];
                        }c;
                        union
                        {
                        long double b;
                        char str2[16];
                        }d;

                          ::memset(&c.str1, 0x00, 16);
                          ::memset(&d.str2, 0x00, 16);
                          ::memcpy(&c.str1\[4\], &esdid, 4);
                          ::memcpy(&c.str1\[8\],&start,4);
                          ::memcpy(&c.str1\[12\], &end, 4);
                          ::memcpy(&d.str2\[4\], &x.esdid, 4);
                          ::memcpy(&d.str2\[8\], &x.start, 4);
                          ::memcpy(&d.str2\[12\], &x.end, 4);
                        
                          return c.a < d.b;
                        
                        //	  return usingrange  < x;
                        //	  if (start < x.start) 
                         //   return start < x.start;
                        

                        // return x.end < end;

                        }

                        };

                        G Offline
                        G Offline
                        Graham Breach
                        wrote on last edited by
                        #12

                        I think you're making it too complicated:

                        struct ESDID
                        {
                        char c[4];

                        bool operator<(const ESDID& other) const
                        {
                        return c[0] < other.c[0] && c[1] < other.c[1] &&
                        c[2] < other.c[2] && c[3] < other.c[3];
                        }
                        }

                        struct usingrange
                        {
                        ESDID esdid;
                        int start;
                        int end;

                        bool operator<(const usingrange& other) const
                        {
                        return esdid < other.esdid && start < other.start &&
                        end < other.end;
                        }
                        }

                        I've used && and < because you do not want operator<() to return true for two different objects when you swap them around.

                        F 1 Reply Last reply
                        0
                        • G Graham Breach

                          I think you're making it too complicated:

                          struct ESDID
                          {
                          char c[4];

                          bool operator<(const ESDID& other) const
                          {
                          return c[0] < other.c[0] && c[1] < other.c[1] &&
                          c[2] < other.c[2] && c[3] < other.c[3];
                          }
                          }

                          struct usingrange
                          {
                          ESDID esdid;
                          int start;
                          int end;

                          bool operator<(const usingrange& other) const
                          {
                          return esdid < other.esdid && start < other.start &&
                          end < other.end;
                          }
                          }

                          I've used && and < because you do not want operator<() to return true for two different objects when you swap them around.

                          F Offline
                          F Offline
                          ForNow
                          wrote on last edited by
                          #13

                          just tried it that did it thank you :)

                          1 Reply Last reply
                          0
                          Reply
                          • Reply as topic
                          Log in to reply
                          • Oldest to Newest
                          • Newest to Oldest
                          • Most Votes


                          • Login

                          • Don't have an account? Register

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • World
                          • Users
                          • Groups