Using struct as KEY and VALUE for map. find() operation giving error

10,511

Solution 1

Your declaration of operator< is off.

struct keyInfo
{
  string Key1; 
  string Key2; 

  bool keyInfo::operator <(keyInfo &A) const
    { return ((this->Key1<A.Key1)&&(this->Key2<A.Key2)); }
};

... and for several reasons:

  1. It is an error to prefix the declaration with the class name within the class. You only should do so if you define it outside the class. Some compilers are laxist, but the Standard says you should not do this.
  2. The reason you cannot compile is that operator< should accept both its operands either as values (for simple things) or by const&. Here you forgot the const for A.
  3. The definition is incorrect, your operator< has its semantics off as the properties of antisymmetry is not respected.
  4. It is recommended that binary operators be declared as free functions outside the class.

All in all, the correct declaration and definition are:

struct keyInfo {
  std::string Key1;
  std::string Key2;
};

inline bool operator<(keyInfo const& left, keyInfo const& right) {
  if (left.Key1 < right.Key1) { return true; }
  if (left.Key1 > right.Key1) { return false; }
  return left.Key2 < right.Key2;
}

If you can use Boost, a "simple" way to implement this is:

inline bool operator<(keyInfo const& left, keyInfo const& right) {
  return boost::tie(boost::cref(left.Key1) , boost::cref(left.Key2))
       < boost::tie(boost::cref(right.Key1), boost::cref(right.Key2));
}

Solution 2

Change parameter to const keyInfo& A:

bool keyInfo::operator <(const keyInfo &A) const  // keyInfo:: is unrequired here

In std::map the key is held as const T so when the std::map implementation invokes keyInfo.operator<() it is passing a const keyInfo&, which cannot be converted to a keyInfo&.

Share:
10,511
N D Thokare
Author by

N D Thokare

Updated on June 04, 2022

Comments

  • N D Thokare
    N D Thokare almost 2 years

    Code in c++:

    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    struct keyInfo
    {
      string Key1; 
      string Key2; 
    
      bool keyInfo::operator <(keyInfo &A) const
        { return ((this->Key1<A.Key1)&&(this->Key2<A.Key2)); }
    };
    
    struct valueInfo
    { 
      int value1; 
      int value2; 
      int value3; 
    
      valueInfo(const int A,const int B,const int C) : 
        value1(A),value2(B),value3(C) {}
    };
    typedef std::map<keyInfo, valueInfo> MapTYPE;
    
    int main()
    {
      MapTYPE TMap;
      keyInfo K;
      K.Key1="main";
      K.Key2="i";
      valueInfo V(-2,-3322,9000);
    
      TMap.insert(MapTYPE::value_type(K,V));
      MapTYPE::iterator It1=TMap.find(K);
      It1=TMap.find(K);
      if(It1!=TMap.end())
        std::cout<<"Success(K): "<<It1->second.value2<<std::endl;
    
      keyInfo E;
      E.Key1="main";
      E.Key2="j";
      //TMap.insert(std::pair<keyInfo,valueInfo>(E,V));
      MapTYPE::iterator It2=TMap.find(E);
      if (It2!=TMap.end())
         std::cout<<"Success(E): "<<(It2->second).value3<<std::endl;
    
      cin.get();
      return 0;
     }
    

    When I compile this code it gave me the error:

    error C2679: binary '<' : no operator found which takes a right-hand operand of type 'const keyInfo1' (or there is no acceptable conversion)

    Please let me know where I'm going wrong? Any help is highly appreciated. Thanks.

    I have tried to implement own operator and used in map<>, code looks as follows:

    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    struct keyInfo
    {
      string Key1; 
      string Key2; 
    
      /*bool keyInfo::operator()(keyInfo const& Left,keyInfo const& Right) const{
          return ((Left.Key1<Right.Key1)&&(Left.Key2<Right.Key2));
      }*/
    };
    
    struct LessComparer{
        bool operator()(keyInfo const& Left,keyInfo const& Right) const{
            return !(Left.Key1==Right.Key1 && Left.Key2==Right.Key2);
        }
    };
    
    struct valueInfo
    { 
      int value1; 
      int value2; 
      int value3; 
    
      valueInfo(const int A,const int B,const int C) : 
        value1(A),value2(B),value3(C) {}
    };
    typedef std::map<keyInfo, valueInfo, LessComparer> MapTYPE;
    
    int main()
    {
      MapTYPE TMap;
      keyInfo K;
      K.Key1="main";
      K.Key2="i";
      valueInfo V(-2,-3322,9000);
    
      TMap.insert(MapTYPE::value_type(K,V));
      MapTYPE::iterator It1=TMap.find(K);
      It1=TMap.find(K);
      if(It1!=TMap.end())
        std::cout<<"Success(K): "<<It1->second.value2<<std::endl;
    
      keyInfo E;
      E.Key1="main";
      E.Key2="j";
      //TMap.insert(std::pair<keyInfo,valueInfo>(E,V));
      MapTYPE::iterator It2=TMap.find(E);
      if (It2!=TMap.end())
         std::cout<<"Success(E): "<<(It2->second).value3<<std::endl;
    
      cin.get();
      return 0;
     }
    

    Here I'm using operator() to return 0 iff both Key1 and Key2 of Left and Right are equal. I think this is the same way map::less works, I mean it return false only if equality condition is satisfied.

    It works fine in first case i.e. TMap.find(K) where same key is found. But during call in second case i.e. TMap.find(E) it pops up an error saying:

    "Debug assertion failed"
    Expression: Invalid operator <
    
    • Bo Persson
      Bo Persson about 12 years
      In addition to making the parameter const, you should also consider if you really want to have both keys less than each other. What happens if Key1 is equal to A.Key1?
  • N D Thokare
    N D Thokare about 12 years
    I have changed parameter to const keyInfo& A , still the same occurs.
  • Matthieu M.
    Matthieu M. about 12 years
    @EthanSteinberg: thanks, but I don't remember off the top of my head if the boost:cref call is necessary. I think you can get away without it with tie... but just didn't want to take any chance here.
  • N D Thokare
    N D Thokare about 12 years
    I have tried using own comparer. can you reply to link: Using Own Comparator
  • N D Thokare
    N D Thokare about 12 years
    I have tried using own comparer. can you reply to link: Using Own Comparator