Заставить найти работу с набором структур - PullRequest
7 голосов
/ 03 мая 2011

Я использую набор для хранения структур, которые содержат несколько строк.Я хочу использовать функцию find () для множеств.Однако, так как набор содержит структуры, он не работает.Я хочу, чтобы find () посмотрел на одну из строк в структуре, когда она найдет.Как это можно сделать?

Вот код, который я пытался использовать.Он работает нормально, за исключением части, где используется find ().

#include <iostream>
#include <string>
#include <set>
using namespace std;

struct test
{
    string key;
    string data;
};

bool operator<(const test & l, const test & r)
{
    return l.key < r.key;
}

bool operator==(const test & l, const test & r)
{
    return l.key == r.key;
}

set<test> s;

int main()
{
    test newmember;
    newmember.key = "key";
    newmember.data = "data";
    s.insert(newmember);
    s.find("key");
}

Вот сообщения об ошибках, когда я пытаюсь скомпилировать его:

test.cpp:30:7: error: no matching member function for call to 'find'
    s.find("key");
    ~~^~~~
In file included from test.cpp:3:
In file included from /usr/include/c++/4.2.1/set:65:
/usr/include/c++/4.2.1/bits/stl_set.h:429:7: note: candidate function not viable: no known conversion from 'const char [4]' to 'const key_type' (aka 'const test') for 1st argument
      find(const key_type& __x)
      ^
/usr/include/c++/4.2.1/bits/stl_set.h:433:7: note: candidate function not viable: no known conversion from 'const char [4]' to 'const key_type' (aka 'const test') for 1st argument
      find(const key_type& __x) const
      ^
1 error generated.

Ответы [ 2 ]

12 голосов
/ 03 мая 2011

Я предлагаю вам operator< и operator== для вашей структуры, вместо того, чтобы перегружать глобальный оператор, я считаю, что он намного чище;пример:

struct test
{
  string key;
  string data;

  bool operator<(const test& rhs) const
  {
    return key < rhs.key;
  }

  bool operator==(const test& rhs) const
  {
    return key == rhs.key;
  }
};

Теперь перейдем к вашей реальной проблеме - вы передаете строку в функцию find(), но она принимает только структуры типа test.Для этого добавьте конструктор для автоматического преобразования, чтобы окончательная структура выглядела следующим образом:

struct test
{      
  string key;
  string data;

  test(const std::string& strKey = "", const std::string& strData = "")
  : key(strKey),
    data(strData) {}

  bool operator<(const test& rhs) const
  {
    return key < rhs.key;
  }

  bool operator==(const test& rhs) const
  {
    return key == rhs.key;
  }
};

Тогда передача строки в find() автоматически вызовет конструктор и создаст временный test структура, содержащая только соответствующий ключ.Обратите внимание, что в этом особом случае конструктор не должен быть объявлен explicit.

2 голосов
/ 03 мая 2011

Чтобы иметь возможность поместить ваши структуры в set, вы должны указать operator< для своей структуры. Вы можете получить результат operator<, сравнивая соответствующие строковые элементы.

Чтобы использовать find, вы можете указать operator==, чтобы ваша структура возвращала true, если соответствующие строковые члены равны.

Пример:

    // code from your question used here

    int main()

{
    test newmember;
    newmember.key = "key";
    newmember.data = "data";

    test findMember;
    findMember.key = "key";
    // as operator== and operator< doesn't care about data field we can left it be
    // initialized by default constructor

    s.insert(newmember);
    s.find(findMember);
}

Если вы хотите вызвать find() с параметром string, вы можете предоставить неявный конструктор из string для вашей структуры test, например, так:

struct test {
//...
  test(const string &in_key) : key(in_key) {}
//...
};

Но использование неявных конструкторов не очень хорошая техника, потому что это может привести к непредсказуемым преобразованиям где-то в вашем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...