Какой итератор вернуть для несуществующей карты Как подписать? - PullRequest
1 голос
/ 21 апреля 2010

Я хочу иметь функцию, которая ищет ключ в коллекции карт и возвращает итератор найденного ключа. Но что следует вернуть, если ключ не найден? Я не могу вернуть map :: end, поскольку коллекция карт может быть пустой.

Спасибо.

map<string, string>::iterator CConfFile::GetKey(const string &SectionName, const string &KeyName)
{
    maps<string, map<string, string> >::const_iterator Section = _Sections.find(SectionName);
    if (Section != _Sections.end()) {

        map<string, string> &Keys = SectionPtr->second;

        map<std::string, string>::const_iterator Key = Keys.find(KeyName);
        if (Key != Keys.end())
            return Key;
    }

    cerr << "Key " << KeyName << "not found\n";
    return WHAT???;
}

Ответы [ 5 ]

3 голосов
/ 21 апреля 2010

Если вы возвращаете итератор, то это означает, что можно фактически выполнять итерацию по всем значениям. Если это действительно так, вам все равно придется возвращать пользовательский тип итератора, и у вас не должно возникнуть проблем с обозначением специального конечного итератора.

Если итератор не предназначен для использования в качестве итератора, может быть лучше вернуть указатель на найденный объект и нулевой указатель, если их нет.

1 голос
/ 21 апреля 2010

Вы можете определить свой собственный прокси-класс итератора, который оборачивает итератор карты и передает ему все операции. Тогда ваш класс может иметь специальное «конечное» значение, и вы можете вернуть это значение для not found. Для сравнения, вызывающей стороне нужен способ получить конечный прокси-итератор.

Если вы хотите быть действительно флэш-памятью, ваш итератор может знать, как «шагнуть вперед» от конца одной содержащейся карты до начала следующей, чтобы его можно было использовать для перебора всех карт в коллекция. По общему признанию не в ключевом заказе.

Другой вариант - вернуть пару (итератор, bool). Ваш «глубокий поиск» уже не возвращает тип, который функции поиска обычно возвращают при вызове с контейнером (то есть тип итератора контейнера), так что вы можете просто пойти на полное изменение.

Итераторы не обязаны конструироваться по умолчанию, хотя часто это так. Так что на самом деле немного сложно иметь «бессмысленный итератор» и быть правильно переносимым. Однако вы можете попробовать создать итератор карты по умолчанию, и, если он работает в вашей реализации, используйте его в случае, если bool имеет значение false.

Я не уверен, что Boost.Optional делает с типами, которые не могут быть созданы по умолчанию, но это может быть полезно в качестве возвращаемого значения.

0 голосов
/ 22 апреля 2010

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

Я считаю вашу проблему очень интересной. Мы могли бы определить новый универсальный класс многоключевой карты, который позволяет вести себя как карта> и, кроме того, как карта, T>, позволяя перебирать все элементы в коллекции. Boost.Multi-Index позволяет определить несколько индексов для коллекции, но я не думаю, что разные индексы могут перебирать разные типы. Я проверю это и вернусь с дополнительной информацией.

Я не знаю, какие другие виды использования вашей карты карт, но если вам не нужно перебирать карту keyName, вы можете преобразовать ее в карту, строка>, и вы сможете вернуть только карту, строку> :: end.

0 голосов
/ 21 апреля 2010

Вы должны использовать map::end, поскольку оно не указывает на последнее значение, но это специальное значение, означающее «вы достигли конца списка» и не содержащее никакого значения.

Чтение http://msdn.microsoft.com/en-US/library/c84shb7e%28v=VS.80%29.aspx

Фокус на обзор и замечания.

0 голосов
/ 21 апреля 2010

Вы можете создать специальный класс NotAKey (см. Null-Object-Pattern ), а затем иметь карту по умолчанию, которая содержит только один объект этого класса. Когда ключ не найден или карта не существует, вы просто возвращаете этот специальный итератор.

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

EDIT : Я думаю, что ответ sbi намного лучше, чем мой, только вы не должны возвращать указатель, но ссылку, а затем использовать ссылку на Null- Объект (может быть глобальным одноэлементным) вместо нулевого указателя.

...