Почему стандартные адаптеры контейнеров C ++ не обеспечивают четкую функцию? - PullRequest
23 голосов
/ 30 января 2009

Кто-нибудь знает, почему std :: queue, std :: stack и std :: priority_queue не предоставляют функцию-член clear()? Я должен подделать один такой:

std::queue<int> q;
// time passes...
q = std::queue<int>();  // equivalent to clear()

IIRC, clear() предоставляется всем, что может служить базовым контейнером. Есть ли веская причина для того, чтобы адаптеры контейнера не предоставляли это?

Ответы [ 6 ]

19 голосов
/ 30 января 2009

Ну, я думаю, это потому, что clear не считался допустимой операцией для очереди, priority_queue или стека (кстати, deque - это не адаптер, а контейнер).

Единственная причина использовать контейнер очередь адаптера вместо контейнера Deque, чтобы дать понять, что вы выполнение только операций с очередями и других операций нет. (со страницы sgi в очереди)

Таким образом, при использовании очереди все, что вы можете сделать, это элементы push / pop; очистка очереди может рассматриваться как нарушение концепции FIFO. Следовательно, если вам нужно очистить свою очередь, возможно, это не совсем очередь, и вам лучше использовать деку.

Тем не менее, эта концепция вещей немного ограничена, и я думаю, что очистка очереди, как и вы, достаточно справедлива.

11 голосов
/ 30 января 2009

У Deque есть clear (). См., Например, http://www.cplusplus.com/reference/stl/deque/clear.html.

Однако очереди нет. Но в любом случае, почему вы выбираете очередь вместо deque?

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

(http://www.sgi.com/tech/stl/queue.html)

Так что, я думаю, clear () не является операцией с очередями.

2 голосов
/ 30 января 2009

Я бы сказал, что адаптеры контейнеров не являются контейнерами.

1 голос
/ 30 января 2009

Вы МОЖЕТЕ очистить очереди (и std :: stack и priority_queue), если вы наследуете их. Контейнер намеренно оставлен защищенным, чтобы позволить это.

#include <queue>

using namespace std;

class clearable_queue : public queue<int>
{
public:
  void clear()
    {
      // the container 'c' in queues is intentionally left protected
      c.clear();
    }
};   

int main(int argc, char** argv)
{
  clearable_queue a;
  a.clear();
}
0 голосов
/ 30 января 2009

std :: queue, std :: deque и std :: priority_queue являются адаптерами контейнера и предоставляют лишь небольшое количество методов для доступа к базовому контейнеру.

Вы можете очистить нижележащий контейнер, при условии, что вы можете получить к нему доступ. Для этого создайте базовый контейнер для передачи в конструктор apadptor. Например:

std::deque< int > d;
std::queue< int > q( d );

... time passes ...

d.clear();

Редактировать: дополнительная информация

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

0 голосов
/ 30 января 2009

Я думаю, это зависит от реализации - до недавнего времени у Microsoft STL не было четких данных по нескольким контейнерам. (теперь, например, этот быстрый результат Google )

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

Я думаю, что стандарт обозначает очистку как стирание по всему диапазону итераторов, поэтому большинство реализаций предоставит вышеизложенное. ( например, Dinkumware's )

...