2013-12-14 4 views
6

Для набора (ов) СТЛ, кажется, что вы должны быть в состоянии сказать:Почему C++ нельзя установить итераторы в bool?

if(s.find(x)) { 
    //Something 
} 

в отличие от

if(s.find(x) != s.end()) { 
    //Something 
} 

Кроме того, если установить-итераторы может быть приведен к типу BOOL (истина если внутренний указатель не равен нулю), вы сможете. Почему у STAR нет итераторов этой простой функции? Было ли это намеренно опущено?

ПОЯСНЕНИЕ:

В качестве альтернативы, Сет может просто набор :: содержит (х) метод, который возвращает логическое значение непосредственно, но это, кажется, не будет реализовано либо. Я знаю, что это только пару символов, но в том случае, когда s является возвращаемое значение некоторой функции, это может быть неприятно из-за необходимости создания временной переменной, то есть (предположим, т имеет тип map<int,set<int>>)

const set<int>& s = m[i]; 
return s.find(x) != s.end(); 

в отличие от

return m[i].contains(x); 

или

return m[i].find(x); 

EDIT:

Я не знал, что метод count() может использоваться как contains(). Проголосовал за закрытие, так как этот вопрос не правильно отражает то, что я действительно должен был спросить: У STL :: set есть метод «содержит»?

+2

Зачем вам нужно писать 's.find (x)'? Итераторы - это позиции, и, похоже, нет веской причины, почему позиция имеет логическое состояние. –

+3

Семантически, итераторы 'end' и' null' - это два разных понятия. – bcrist

+0

@ DietmarKühl: То же самое можно сказать о указателях, но они могут быть неявно преобразованы в 'bool'! –

ответ

9

Итераторы в стандартной библиотеке C++ не знают о контейнере, откуда они пришли, и поэтому они не могут вообще знать, дошли ли они до конца. Это преднамеренно, чтобы позволить итераторам быть максимально легкими –, вы не платите за то, что не используете. (Итераторы обобщают идею указателей, а указатель - итератор.)

Вы всегда можете создать свой собственный самоидентичный итератор как пару собственных итераторов.

В самом деле, некоторые люди утверждают, что такая пара, или диапазон является более естественным способом говорить о коллекции, и есть библиотеки, а также библиотеки, адаптеры для осуществления диапазонов (например, Boost.Range) ,

Update: итераторов более низкий уровень, чем диапазоны, и это спорно, какая концепция является лучшим решением (хотя можно было бы необходимо определить проблемы первыми). Итераторы немного более гибкие; например, если вы мутируете контейнер во время итерации по нему, вам придется «обновить» все пары диапазонов, чтобы получить новое «конечное» значение. (Или, в противном случае, перейти к полностью «ориентированному на диапазон» алгоритмическому стилю.) Альтернативно вы можете сохранить ссылку на контейнер в итераторе и пересчитать end() каждый раз, когда это необходимо. Уже вы можете увидеть, как много нетривиальных деталей, и стандартная библиотека C++ просто решила не делать эти варианты для вас, а вместо этого дает вам только строительных блоков, чтобы написать решение, которое лучше всего подходит для вашей собственной проблемы.

+0

Это * вероятно * ответ, никакой специальный случай никогда не предлагался. Но речь идет не об итераторах в целом, а конкретно о 'set :: iterator'. –

+0

@SteveJessop: Было бы сложно поддерживать инварианты диапазона, пока вы мутируете контейнеры, поэтому итераторы, вероятно, являются более общим решением. –

+1

Конечно, итераторы в целом более общие, чем 'set :: iterator', в частности, я не могу не согласиться с этим :-) Так как множество мутаций в частности не отменяет итераторов (кроме удаленных), я не 'действительно посмотрите, как мутация будет серьезно препятствовать реализации 'set' из реализации' operator bool() '(или что-то более безопасное), так что конечные итераторы возвращают false и другие итераторы true. –

Смежные вопросы