Topic: Why no clear() member in container adaptors?


Author: cbarron3@ix.netcom.com (Carl Barron)
Date: Sat, 4 Nov 2006 01:15:07 CST
Raw View
Randy <rmaddox@isicns.com> wrote:

>
> I hear what you are saying about std::queue modelling the behavior of
> the queue concept, and that point certainly cannot be argued against,
> but ...
>
> In the real world where queues are actually used it is not at all
> uncommon to want to flush a queue, discarding whatever is in it at the
> time.  In fact, that is exactly how this question arose.  I was in a
> code review where the developer needed to flush a queue and she had a
> loop popping each item off the queue until it was empty.  It was
> suggested that she just use clear() instead since that succinctly
> expressed the intent.
>
    So is assignment of an empty queue to the queue. :)

template <class T,class C>
inline void flush_queue(std::queue<T,C> &c)
{ c = std::queue<T,C>();}

  Simple and just as meeningful Also likely to be at least as efficient
as a programmers loop.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Seungbeom Kim <musiphil@bawi.org>
Date: Sun, 5 Nov 2006 22:59:39 CST
Raw View
Greg Herlihy wrote:
>
> So in this case, the public interface of a std::queue class should
> model the behavior of a queue - which is of course a special kind of
> container: items can be removed only on a one-by-one basis, and always
> in the same order in which the iterms were inserted. A public clear()
> method for a queue class, while perhaps convenient, would effectively
> allow a client to circumvent these constraints and remove multiple
> items at the same time and without respect to their insertion order. So
> a queue class with a clear() method would - strictly speaking - no
> longer live up to its billing by behaving completely like a queue.

But a client can use only the public interface of queue to clear it,
though inefficient. How does it break the modelling to provide a
function that uses only the public members to fulfil its task?

>
> Since the needs of a queue subclass are likely to differ from those of
> a queue client, the protected interface of std::queue should be
> expected to differ from its public interface. And in fact, it is hard
> to envision how a std::queue subclass do anything useful unless it had
> access to the queue's underlying container. And indeed if a subclass
> can be implemented entirely in terms of its base class's public
> interface, then it is often worthwhile to implement the subclass as an
> adapter class instead - just as the std::queue class itself adapts a
> container class instead of deriving from one.

But how can a derived class be called a subtype of the base class if it
can access the underlying container directly and can do anything with
it, even something that can break the contract of the base class? What
do you think of the design of my_queue derived from std::queue and
providing a clear() function that simply calls c.clear() -- is this an
example of "anything useful" you mentioned, or of breaking the contract?

A: "I cannot do this with std::queue -- it's forbidden!"
B: "Then derive a class from it and do it there."

This is not supposed to be a role of derived classes, isn't it?

--
Seungbeom Kim

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Randy" <rmaddox@isicns.com>
Date: Mon, 16 Oct 2006 12:54:09 CST
Raw View
I was wondering if anyone could explain the rationale behind the design
of the container adaptors, such as queue for example, which do not
provide access to the underlying container's clear() method, but do
provide a protected member for that container so it looks like you
could derive from the adaptor and use that container directly.

Thanks in advance for any insight you may be able to offer.

Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Tue, 17 Oct 2006 11:25:52 CST
Raw View
Randy wrote:
> I was wondering if anyone could explain the rationale behind the design
> of the container adaptors, such as queue for example, which do not
> provide access to the underlying container's clear() method, but do
> provide a protected member for that container so it looks like you
> could derive from the adaptor and use that container directly.

Access levels in C++ enable a class to offer three distinct programming
interfaces: a public interface (also known as a client interface) that
is available to all, a private interface, available only to the
implementation of the class itself, and a protected interface -
available both to the class itself and also to any subclasses that may
derive from it.

So in this case, the public interface of a std::queue class should
model the behavior of a queue - which is of course a special kind of
container: items can be removed only on a one-by-one basis, and always
in the same order in which the iterms were inserted. A public clear()
method for a queue class, while perhaps convenient, would effectively
allow a client to circumvent these constraints and remove multiple
items at the same time and without respect to their insertion order. So
a queue class with a clear() method would - strictly speaking - no
longer live up to its billing by behaving completely like a queue.

Since the needs of a queue subclass are likely to differ from those of
a queue client, the protected interface of std::queue should be
expected to differ from its public interface. And in fact, it is hard
to envision how a std::queue subclass do anything useful unless it had
access to the queue's underlying container. And indeed if a subclass
can be implemented entirely in terms of its base class's public
interface, then it is often worthwhile to implement the subclass as an
adapter class instead - just as the std::queue class itself adapts a
container class instead of deriving from one.

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Randy" <rmaddox@isicns.com>
Date: Fri, 20 Oct 2006 14:03:48 CST
Raw View
Greg Herlihy wrote:
> Randy wrote:
> > I was wondering if anyone could explain the rationale behind the design
> > of the container adaptors, such as queue for example, which do not
> > provide access to the underlying container's clear() method, but do
> > provide a protected member for that container so it looks like you
> > could derive from the adaptor and use that container directly.
>
 [snip]
>
> So in this case, the public interface of a std::queue class should
> model the behavior of a queue - which is of course a special kind of
> container: items can be removed only on a one-by-one basis, and always
> in the same order in which the iterms were inserted. A public clear()
> method for a queue class, while perhaps convenient, would effectively
> allow a client to circumvent these constraints and remove multiple
> items at the same time and without respect to their insertion order. So
> a queue class with a clear() method would - strictly speaking - no
> longer live up to its billing by behaving completely like a queue.
>
 [snip]
> Greg
>
> ---

I hear what you are saying about std::queue modelling the behavior of
the queue concept, and that point certainly cannot be argued against,
but ...

In the real world where queues are actually used it is not at all
uncommon to want to flush a queue, discarding whatever is in it at the
time.  In fact, that is exactly how this question arose.  I was in a
code review where the developer needed to flush a queue and she had a
loop popping each item off the queue until it was empty.  It was
suggested that she just use clear() instead since that succinctly
expressed the intent.

Later, of course, we determined there is no clear() member for any of
the container adapters and wondered why this should be the case since
the underlying containers do in fact support this operation, which is
commonly needed.

Guess we'll just have to work around this issue.

Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Andrei Polushin" <polushin@gmail.com>
Date: Fri, 20 Oct 2006 15:53:33 CST
Raw View
Greg Herlihy wrote:
> Randy wrote:
>> I was wondering if anyone could explain the rationale behind the design
>> of the container adaptors, such as queue for example, which do not
>> provide access to the underlying container's clear() method, but do
>> provide a protected member for that container so it looks like you
>> could derive from the adaptor and use that container directly.
>
> Access levels in C++ enable a class to offer three distinct programming
> interfaces: a public interface (also known as a client interface) that
> is available to all, a private interface, available only to the
> implementation of the class itself, and a protected interface -
> available both to the class itself and also to any subclasses that may
> derive from it.

The "three interfaces" is just a metaphor. In addition to those
three, we can talk about a library-wide interface defined in the
"requirements" sections of the standard. The requirements section
for sequences contains the definition of clear() for some reason.

> So in this case, the public interface of a std::queue class should
> model the behavior of a queue - which is of course a special kind of
> container: items can be removed only on a one-by-one basis, and always
> in the same order in which the iterms were inserted. A public clear()
> method for a queue class, while perhaps convenient, would effectively
> allow a client to circumvent these constraints and remove multiple
> items at the same time and without respect to their insertion order. So
> a queue class with a clear() method would - strictly speaking - no
> longer live up to its billing by behaving completely like a queue.

Is queue a sequence? Formally - not, queue is "a container adaptor".
Then why deque is a sequence? The deque is a "double-ended-queue", so
both queue and deque should share the same metaphor, shouldn't them?
And if they share the same metaphor, why they are described by
different requirements?

In particular, the following members, otherwise redundant, could be
provided to generalize the metaphor of sequence adaptors:

    a.max_size()
    a.empty()
    a.clear()
    a.swap(b)
    swap(a, b)

The overall reasons to have this members (in a library) are

    - convenience,
    - interface generalization and predictability,
    - efficiency.

I suggest them to be added to container adaptors.

--
Andrei Polushin

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]