Используя struct как KEY и VALUE для карты.операция find (), выдающая ошибку - PullRequest
1 голос
/ 10 марта 2012

Код на С ++:

#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;
 }

Когда я компилировал этот код, он выдал ошибку:

ошибка C2679: двоичный файл <<: не найден оператор, который принимает правый операнд типа «const keyInfo1» (или нет допустимого преобразования) </p>

Пожалуйста, дайте мне знать, где я иду не так? Любая помощь высоко ценится. Благодаря.

Я попытался реализовать собственный оператор и использовал в map <>, код выглядит следующим образом:

#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;
 }

Здесь я использую operator () для возврата 0, если и Key1, и Key2 слева и справа равны. Я думаю, что это то же самое, что map :: less работает, я имею в виду, что он возвращает false, только если выполняется условие равенства.

Он отлично работает в первом случае, т. Е. TMap.find (K), где найден тот же ключ. Но во время вызова во втором случае, т. Е. TMap.find (E), появляется сообщение об ошибке:

"Debug assertion failed"
Expression: Invalid operator <

Ответы [ 2 ]

6 голосов
/ 10 марта 2012

Ваше объявление operator< отключено.

struct keyInfo
{
  string Key1; 
  string Key2; 

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

... и по нескольким причинам:

  1. Ошибочно ставить объявление перед именем класса внутри класса. Вы должны делать это только в том случае, если вы определяете это вне класса. Некоторые компиляторы слабы, но Стандарт говорит, что вы не должны этого делать.
  2. Причина, по которой вы не можете скомпилировать, заключается в том, что operator< должен принимать оба своих операнда либо в качестве значений (для простых вещей), либо const&. Здесь вы забыли const для A.
  3. Определение неверное, у вашего operator< семантика отключена, поскольку свойства antisymmetry не соблюдаются.
  4. Рекомендуется объявлять бинарные операторы как свободные функции вне класса.

В целом, правильное объявление и определение:

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

Если вы можете использовать Boost, «простой» способ реализовать это:

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));
}
1 голос
/ 10 марта 2012

Измените параметр на const keyInfo& A:

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

В std::map ключ сохраняется как const T, поэтому, когда реализация std::map вызывает keyInfo.operator<(), он передает const keyInfo&,который не может быть преобразован в keyInfo&.

...