size_t: оператор?(и способ использовать unordered_set) - PullRequest
6 голосов
/ 05 июля 2011

Что такое

operator size_t () const

Среда: Visual Studio 2010 Professional


TL;DR

Сегодня я искал способ использования std::tr1::unordered_set.Поскольку в прошлый раз я спросил , как использовать std::map, я решил выяснить это сам.

Я погуглил, и большинство результатов подсказали мне структуру для хеширования.Путь выглядел немного сложным для меня, и я продолжал искать и, наконец, наткнулся на другой подход.

Мне нужно реализовать

bool operator == (const edge & another) const

и

operator size_t () const

Полученный код близок к концу вопроса.

== знаком без проблем.size_t тоже знакомо.Но что такое operator size_t?

Похоже, equals и hashCode для Java, которые должны быть переопределены вместе в соответствии с Effective Java.Но я не уверен, особенно когда имя size_t.


Полученный код выглядит следующим образом.Полная программа работает нормально и выдает правильные выходные данные.

class edge {
public:
    int x;
    int y;
    edge(int _x, int _y) : x(_x), y(_y) {
    }
    bool operator == (const edge & another) const {
        return (x == another.x && y == another.y);
    }
    operator size_t () const {
        return x * 31 + y;
    }
};

Немного больше:

Not

size_t operator () const

, который не может быть скомпилирован:

error C2143: syntax error : missing ';' before 'const'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2059: syntax error : '{'
error C2334: unexpected token(s) preceding '{'; skipping apparent function body

Даже не

int operator size_t () const

, но, как я вижу, функция возвращает int.Код ошибки следующий:

error C2549: user-defined conversion cannot specify a return type

Ответы [ 5 ]

14 голосов
/ 05 июля 2011

Это оператор приведения типа .В основном обеспечивает неявное преобразование объекта в указанный тип, в данном случае size_t.

РЕДАКТИРОВАТЬ:

Скажем, у вас есть функция, определенная следующим образом:

void Foo( size_t x )
{
  // do something with x
}

Если ваш класс edge определяет оператор приведения типа для преобразования в size_t, вы можете сделать следующее:

edge e;
Foo( e );

Компилятор автоматически преобразует объект edgeдо size_t.Как говорит @litb в разделе комментариев, не делайте этого.Неявные преобразования могут вызвать проблемы, позволяя компилятору выполнять преобразования, когда вы, возможно, не предполагали, что это произойдет.

Вместо этого вам следует определить функцию-член, такую ​​как edge::to_size_t() (я знаю, это ужасное имя) для выполненияпреобразование.

Например, std::string определяет функцию-член std::string::c_str() вместо определения оператора приведения типа для преобразования в const char *.

EDIT 2: Извините, я недостаточно внимательно прочитал ваш вопрос.Теперь я вижу, что вы пытаетесь использовать свой класс в std::unordered_set.В этом случае вы должны определить функторы, которые выполняют операции хеширования и сравнения для вашего класса.В качестве альтернативы, вы можете предоставить для вашего класса специализации шаблонов std::hash и std::equal_to и не указывать необязательные параметры шаблона при создании объекта unordered_set.

Как вы уже задали в этом вопросе,это очень похоже на функцию-член Java hashCode(), но поскольку не все классы C ++ являются производными от общего базового класса, такого как классы Java, она не реализована как переопределяемая функция базового класса.

2 голосов
/ 05 июля 2011

Что такое operator size_t () const?

Это функция преобразования . Это функция, которая позволяет неявно преобразовать объект вашего класса в тип size_t. Смотрите дополнительную информацию и примеры в ссылке, которую я предоставил. Hth.

2 голосов
/ 05 июля 2011

Это оператор преобразования, на что намекает error C2549: user-defined conversion cannot specify a return type. Он определяет, как ваш тип может быть преобразован в size_t в этом случае. В общем, operator X() {...} указывает, как создать X из вашего типа.

1 голос
/ 05 июля 2011

Это неявный оператор преобразования.По сути, он позволяет использовать объект вашего класса в контексте, где ожидается size_t (вызывая этот оператор для выполнения преобразования).

Чтобы использовать unordered_set, вам нужно чтобы иметь какую-то функцию hashignВ этом случае он маскируется как operator size_t, что я не очень рекомендую, потому что просто запутывает тот факт, что это хеш-функция.Я хотел бы просто определить настоящую хэш-функцию / функтор и использовать ее вместо этого.Это будет более понятно, и будущие сопровождающие будут вам благодарны.

1 голос
/ 05 июля 2011

В любом классе Foo, operator T () const является оператором приведения , который позволяет вам разыграть Foo в T:

Foo x;
T y = x; // invokes Foo::operator T() const

Например, std::fstream имеет оператор приведения к типу bool, поэтому вы можете использовать его в выражениях типа if (mystream) ....


В ответ на вашу потребность в использовании неупорядоченных контейнеров: вам потребуется реализовать хеш-функцию или функциюобъект, который соответствует подписи size_t (const Foo &).Если вы хотите сделать это с наименьшим видимым воздействием на код пользователя, специализируйте std::hash<Foo>:

size_t my_magic_hash(const Foo &); // defined somehow
namespace std {
  template <>
  struct hash<Foo> : public std::unary_function<const Foo &, std::size_t>
  {
    inline std::size_t operator()(const Foo & x) const
    {
      return my_magic_hash(x);
    }
  };
}

Теперь мы можем использовать std::unordered_set<Foo> напрямую, при условии, что Foo обеспечивает operator==.

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